FC2カウンター FPGAの部屋 カーブ、直線用白線間走行用畳み込みニューラルネットワーク16(SDK)
FC2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

カーブ、直線用白線間走行用畳み込みニューラルネットワーク16(SDK)

カーブ、直線用白線間走行用畳み込みニューラルネットワーク15(Vivadoプロジェクト)”の続き。

前回は、 curve_conv_nn2_axis3 IP を使用し、直線用のVivado 2017.3 のプロジェクトを修正して、カーブと直線対応のミニ・ロボットカーの走行システムをVivado 2017.3 で作成した。今回は、ハードウェアをエクスポートして、SDKを立ち上げ、アプリケーションソフトを作成して動作を確認してみよう。

まずは、Vivado で File メニューからExport → Export Hardware... を選択して、ハードウェアをエクスポートした。

File メニューから Launch SDK を選択して、SDK を立ち上げた。

SDK で wl_tracing_cnn アプリケーション・プロジェクトを作成した。

wl_tracing_cnn.c を修正して、 wl_tracing_cnn アプリケーション・プロジェクトにコピーした。
curve_tracing_cnn_80_171226.png

ZYBO の電源をONした。コンフィギュレーション・モードはJTAG だ。

SDK の Xilinx メニューから Program FPG を選択して、FPGA にビット・ファイルをコンフィギュレーションした。

wl_tracing_cnn.elf を起動した。
VGA ポートに接続したディスプレイにカメラ画像が表示された。
シリアル・ポートに接続されたTera Term の画面に結果と 3 出力の値が表示された。
curve_tracing_cnn_81_171226.png

成功だ。

wl_tracing_cnn.c を貼っておく。

/* * wl_tracing_cnn.c * *  Created on: 2017/09/18 *      Author: Masaaki */
// ベアメタル・アプリケーションでは、CNN がきちんと動作しているを確認するのみとする
// なお、このアプリケーションはcam_disp3_axis.c を起動してカメラを表示状態にした後で起動する
// 2017/09/19 : 直進、左旋回、右旋回の各出力の値を表示するように変更
// 2017/12/12 : カーブ対応に更新
//

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"

#include "xdmaw4gabor.h"
#include "xdmar4resize_gray.h"
#include "xresize_gray.h"
#include "xcurve_conv_nn2_axis3.h"

#define NUMBER_OF_WRITE_FRAMES    3 // Note: If not at least 3 or more, the image is not displayed in succession.

#define HORIZONTAL_PIXELS    800
#define VERTICAL_LINES        600
#define PIXEL_NUM_OF_BYTES    4

#define FRAME_BUFFER_ADDRESS 0x10000000
#define ALL_DISP_ADDRESS    (HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES)

void cam_i2c_init(volatile unsigned *mt9d111_i2c_axi_lites) {
    mt9d111_i2c_axi_lites[64] = 0x2// reset tx fifo ,address is 0x100, i2c_control_reg
    mt9d111_i2c_axi_lites[64] = 0x1// enable i2c
}

void cam_i2x_write_sync(void) {
    // unsigned c;

    // c = *cam_i2c_rx_fifo;
    // while ((c & 0x84) != 0x80)
        // c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
    usleep(1000);
}

void cam_i2c_write(volatile unsigned *mt9d111_i2c_axi_lites, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
    mt9d111_i2c_axi_lites[66] = 0x100 | (device_addr & 0xfe);   // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    mt9d111_i2c_axi_lites[66] = write_addr;
    mt9d111_i2c_axi_lites[66] = (write_data >> 8)|0xff;         // first data
    mt9d111_i2c_axi_lites[66] = 0x200 | (write_data & 0xff);        // second data
    cam_i2x_write_sync();
}

int main(){
    XDmar4resize_gray xdmar;
    XResize_gray resg;
    XCurve_conv_nn2_axis3 stcnn;
    XDmaw4gabor xdma4g;
    int i;
    uint32_t res;
    int result[4];

    // axis_switch_1, 1to2 ,Select M00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x40), 0x0);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x44), 0x80000000); // disable
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x48), 0x80000000); // disable
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR), 0x2); // Commit registers

    // axis_switch_0, 2to1, Select S00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR+0x40), 0x0);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR), 0x2); // Commit registers

    XDmaw4gabor_Initialize(&xdma4g, 0);
    XDmaw4gabor_Set_frame_buffer0(&xdma4g, FRAME_BUFFER_ADDRESS);
    XDmaw4gabor_Set_frame_buffer1(&xdma4g, FRAME_BUFFER_ADDRESS+ALL_DISP_ADDRESS);
    XDmaw4gabor_Start(&xdma4g);
    XDmaw4gabor_EnableAutoRestart(&xdma4g);

    // mt9d111_inf_axis_0, axi_iic_0, bitmap_disp_cntrler_axi_master_0
    volatile unsigned int *bmdc0_axi_lites;
    volatile unsigned int *bmdc1_axi_lites;
    volatile unsigned int *mt9d111_axi_lites;
    volatile unsigned int *mt9d111_i2c_axi_lites;

    bmdc0_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_0_BASEADDR;
    bmdc1_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_1_BASEADDR;
    mt9d111_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_MT9D111_INF_AXIS_0_BASEADDR;
    mt9d111_i2c_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_AXI_IIC_0_BASEADDR;

    bmdc0_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller 0 start
    bmdc1_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller 1 start
    mt9d111_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)

    // CMOS Camera initialize, MT9D111
    cam_i2c_init(mt9d111_i2c_axi_lites);

    cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0xf00x1);      // Changed regster map to IFP page 1
    cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0x970x20);        // RGB Mode, RGB565

    mt9d111_axi_lites[1] = 0// One_shot_mode is disabled

    XDmar4resize_gray_Initialize(&xdmar, 0);
    XResize_gray_Initialize(&resg, 0);
    XCurve_conv_nn2_axis3_Initialize(&stcnn, 0);

    XDmar4resize_gray_Set_frame_buffer0(&xdmar ,FRAME_BUFFER_ADDRESS);
    XDmar4resize_gray_Set_frame_buffer1(&xdmar ,FRAME_BUFFER_ADDRESS+ALL_DISP_ADDRESS);
    XDmar4resize_gray_Start(&xdmar);
    XDmar4resize_gray_EnableAutoRestart(&xdmar);

    XResize_gray_Start(&resg);
    XResize_gray_EnableAutoRestart(&resg);

    XCurve_conv_nn2_axis3_Start(&stcnn);
    XCurve_conv_nn2_axis3_EnableAutoRestart(&stcnn);

    while(1){
        sleep(1);

        while(!XCurve_conv_nn2_axis3_Get_outs_V_vld(&stcnn)) ;
        printf("out = %d\n", (int)XCurve_conv_nn2_axis3_Get_outs_V(&stcnn));
        for(i=0; i<2; i++){
            XCurve_conv_nn2_axis3_Read_dot2_V_Words(&stcnn, i, &res, 1);
            result[i*2] = res & 0xffff;
            if(result[i*2] & 0x8000// minus
                result[i*2] = 0xffff0000 | result[i*2]; // Sign extension

            result[i*2+1] = (res & 0xffff0000) >> 16;
            if(result[i*2+1] & 0x8000// minus
                result[i*2+1] = 0xffff0000 | result[i*2+1]; // Sign extension
        }
        for(i=0; i<3; i++)
            printf("result[%d] = %x ", i , result[i]);
        printf("\n");
    }

    return(0);
}


  1. 2017年12月26日 05:14 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/4019-bed9e0aa
この記事にトラックバックする(FC2ブログユーザー)