FC2カウンター FPGAの部屋 Vivado HLS で生成した AXI4 Master DMA IP を使用したカメラ画像表示システム6(アプリの変更と30fpsへ)

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

FPGAの部屋

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

Vivado HLS で生成した AXI4 Master DMA IP を使用したカメラ画像表示システム6(アプリの変更と30fpsへ)

Vivado HLS で生成した AXI4 Master DMA IP を使用したカメラ画像表示システム5(ILAコアの削除)”の続き。

前回は、Vivado HLS で生成した AXI4 Master DMA IP を使用したカメラ画像表示システムから 2 つの ILA コアを削除した。今回は、アプリケーションソフトを整備した後で、15 fps のカメラのフレームレートを 30 fps に変更する。

まずは、DMA_Read_addr IP の動作モードのDMA_WRITE_MODE はDMA_Write IP の書き込んでいる画像フレームの1つ前の画像フレームからDMA Read しているモードでこれは正常に動作している。問題は、FREE_RUM_MODE で、これは、3 つの画像フレームからフリーランで読んでるモードなのだが、15 fps でカメラがWrite していて、60 fps でビットマップ・ディスプレイ・コントローラがRead するので、画像フレームバッファが 3 つあると現在、過去が入り混じって画像がぶれてしまう。よって、FREE_RUM_MODE の場合は、画像フレームを 1 つにする必要があるようだ。そのように変更したところ、画像がぶれることは無くなった。
DMA_Read_IP_85_170320.png

cam_disp_hls.c を貼っておく。

/* * cam_disp_hls.c * *  Created on: 2016/08/21 *      Author: Masaaki */


#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xdma_read_addr.h"
#include "xdma_write.h"
#include "sleep.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 DMA_WRITE_MODE
//#define FREE_RUN_MODE

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(){
    XDma_read_addr  dmar, *dmarp;
    XDma_write      dmaw, *dmawp;

    dmarp = &dmar;
    dmawp = &dmaw;

    // Initialization of DMA Read
    if (XDma_read_addr_Initialize(dmarp, 0) != XST_SUCCESS){
        fprintf(stderr,"DMA Read open error\n");
        exit(-1);
    }

    // Initialization of DMA Write
    if (XDma_write_Initialize(dmawp, 0) != XST_SUCCESS){
        fprintf(stderr,"DMA Write open error\n");
        exit(-1);
    }

    // frame buffer settings
#ifdef DMA_WRITE_MODE
    XDma_read_addr_Set_frame_buffer0(&dmar, FRAME_BUFFER_ADDRESS);
    XDma_read_addr_Set_frame_buffer1(&dmar, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES);
    XDma_read_addr_Set_frame_buffer2(&dmar, FRAME_BUFFER_ADDRESS+2*HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES);

    XDma_write_Set_frame_buffer0(&dmaw, FRAME_BUFFER_ADDRESS);
    XDma_write_Set_frame_buffer1(&dmaw, FRAME_BUFFER_ADDRESS+HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES);
    XDma_write_Set_frame_buffer2(&dmaw, FRAME_BUFFER_ADDRESS+2*HORIZONTAL_PIXELS*VERTICAL_LINES*PIXEL_NUM_OF_BYTES);
#else // FREE_RUN_MODE
    XDma_read_addr_Set_frame_buffer0(&dmar, FRAME_BUFFER_ADDRESS);
    XDma_read_addr_Set_frame_buffer1(&dmar, FRAME_BUFFER_ADDRESS);
    XDma_read_addr_Set_frame_buffer2(&dmar, FRAME_BUFFER_ADDRESS);

    XDma_write_Set_frame_buffer0(&dmaw, FRAME_BUFFER_ADDRESS);
    XDma_write_Set_frame_buffer1(&dmaw, FRAME_BUFFER_ADDRESS);
    XDma_write_Set_frame_buffer2(&dmaw, FRAME_BUFFER_ADDRESS);
#endif

    // DMA_read_addr mode set
#ifdef DMA_WRITE_MODE
    XDma_read_addr_Set_mode_V(&dmar, 0); // DMA_WRITE_MODE
#else // FREE_RUN_MODE
    XDma_read_addr_Set_mode_V(&dmar, 1); // FREE_RUN_MODE
#endif

    // mt9d111_inf_axis_0, axi_iic_0, bitmap_disp_cont_axis_0
    volatile unsigned int *mt9d111_axiL;
    volatile unsigned int *cam_iic_axiL;
    volatile unsigned int *bmdc_axiL;

    mt9d111_axiL = (volatile unsigned int *)XPAR_MT9D111_INF_AXIS_0_BASEADDR;
    cam_iic_axiL = (volatile unsigned int *)XPAR_AXI_IIC_0_BASEADDR;
    bmdc_axiL = (volatile unsigned int *)XPAR_BITMAP_DISP_CONT_AXIS_0_BASEADDR;

    // bitmap_disp_cont_axis_0 is started
    bmdc_axiL[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)

    // DMA Start
    XDma_read_addr_DisableAutoRestart(&dmar);
    while(!XDma_read_addr_IsIdle(&dmar)) ;
    XDma_read_addr_Start(&dmar);
    XDma_read_addr_EnableAutoRestart(&dmar);

    XDma_write_DisableAutoRestart(&dmaw);
    while(!XDma_write_IsIdle(&dmaw)) ;
    XDma_write_Start(&dmaw);
    XDma_write_EnableAutoRestart(&dmaw);

    // mt9d111_inf_axis_0 is started
    mt9d111_axiL[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)

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

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

    mt9d111_axiL[1] = 0// One_shot_mode is disabled

    return(0);
}


これで、FREE_RUM_MODE も問題が無くなったので、次は、カメラのフレームレートを 15 fps から 30 fps に向上させることにした。
やり方は、”MT9D111のフレームレートを 15 fps から 30 fps にした”に書いておいた。
早い話が、カメラに供給するクロックを 36 MHz から倍の 72 MHz に変更するということだ。それに合わせて制約も変更する。
具体的には、PS からのクロックの FCLK_CLK2 の周波数設定を 36 MHz から 72 MHz に変更した。
DMA_Read_IP_86_170320.png

もう一度、論理合成、インプリメント、ビットストリームの生成を行い、ハードウェアをエクスポートして、SDKを立ち上げた。
これで、画像のフレームレートが 15 fps から 30 fps に向上した。

このDMAWrite IPとDMA_Read_addr IP の組は使えそうだ。AXI VDMAの説明書を読まなくても簡単に使えるところが良いと思う。
願わくば、DMA_Read_addr IP を使うときのツールのバグが直ってほしいと思う。
  1. 2017年03月24日 05:17 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/3753-17b18d52
この記事にトラックバックする(FC2ブログユーザー)