FC2カウンター FPGAの部屋 画像フィルタを DFX する14(DFX_filter_test プロジェクト7)
fc2ブログ

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

FPGAの部屋

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

画像フィルタを DFX する14(DFX_filter_test プロジェクト7)

画像フィルタを DFX する13(DFX_filter_test プロジェクト6)”の続き。

前回は、通過 IP 、ラプラシアン・フィルタ IP 、ソーベル・フィルタ IP の 3 個の IP を DFX で切り替えるべく Vivado 2021.1 の DFX_filter_test プロジェクトに追加するということで、 Vitis 2021.1 を起動して、プラットフォームとアプリケーション・プロジェクトを作成し、ソースコードを作成した。それをビルドして実機で確認することができた。今回は、そのプロジェクトで DFX として、ラプラシアン・フィルタとソーベル・フィルタを切り替えて動作させてみよう。

DFX_filter_test.c を書き換えて、ラプラシアン・フィルタとソーベル・フィルタのパーシャル・ビット・ファイルをコンフィギュレーションできるようにした。更に、 xlap_filter_axis_hw.h と xsobel_filter_axis_hw.h をインポートした。
DFX2_122_210822.png

ここに、OV5642 のレジスタをセットするための関数 cam_reg_set() を除いたコードを貼っておく。 cam_reg_set() については、”画像フィルタを DFX する13(DFX_filter_test プロジェクト6)”を参照のこと。

// DFX_filter_test.c
// 2021/08/08 by marsee
// 2021/08/09 : Stop the operation of DMA2axis IP on the video side and restart it.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "xil_io.h"
#include "xparameters.h"

#include "xvflip_dma_write.h"
#include "xdma2axis.h"
#include "xthrough_axis.h"
#include "xlap_filter_axis_hw.h"
#include "xsobel_filter_axis_hw.h"

#define CAMERA_DATA_DMA_ADDR    0x10000000

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600

#define XLAP_FILTER_AXIS_BASEADDR   0x40000000
#define XSOBEL_FILTER_AXIS_BASEADDR 0x40000000

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr);

void cam_i2c_init(volatile uint32_t *ov5642_axi_iic) {
    ov5642_axi_iic[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    ov5642_axi_iic[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 uint32_t *ov5642_axi_iic, uint32_t device_addr, uint32_t write_addr, uint32_t write_data){
    ov5642_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    ov5642_axi_iic[66] = (write_addr >> 8) & 0xff;  // address upper byte
    ov5642_axi_iic[66] = write_addr & 0xff;           // address lower byte
    ov5642_axi_iic[66] = 0x200 | (write_data & 0xff);      // data
    cam_i2x_write_sync();
}

int main(){
    XVflip_dma_write XVfilp_dma_write_ap;
    XDma2axis XDma2axis_ap;
    XThrough_axis XTh_axis_ap;
    int inbyte_in;

    XVflip_dma_write_Initialize(&XVfilp_dma_write_ap, 0);
    XDma2axis_Initialize(&XDma2axis_ap, 0);
    XThrough_axis_Initialize(&XTh_axis_ap, 0);

    XVflip_dma_write_Set_fb0_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb1_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb2_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XDma2axis_Set_x_size(&XDma2axis_ap, HORIZONTAL_PIXELS);
    XDma2axis_Set_y_size(&XDma2axis_ap, VERTICAL_LINES);
    XDma2axis_Set_in_V(&XDma2axis_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XThrough_axis_Set_x_size(&XTh_axis_ap, (u32)HORIZONTAL_PIXELS);
    XThrough_axis_Set_y_size(&XTh_axis_ap, (u32)VERTICAL_LINES);

    // vflip_dma_write start
    XVflip_dma_write_Start(&XVfilp_dma_write_ap);
    XVflip_dma_write_EnableAutoRestart(&XVfilp_dma_write_ap);

    // CMOS Camera initialize, ov5642
    cam_i2c_init((volatile uint32_t *)XPAR_AXI_IIC_0_BASEADDR);
    cam_reg_set((volatile uint32_t *)(XPAR_AXI_IIC_0_BASEADDR), (uint32_t)0x78); // OV5642 register set
    Xil_Out32(XPAR_MT9D111_INF_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // ov5642 AXI4-Stream Start
    Xil_Out32((XPAR_MT9D111_INF_AXIS_0_BASEADDR+4), 0);

    // bitmap_disp_cont_axis start
    Xil_Out32(XPAR_BITMAP_DISP_CONT_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // dummy address, start

    // through_axis start
    XThrough_axis_Start(&XTh_axis_ap);
    XThrough_axis_EnableAutoRestart(&XTh_axis_ap);

    // DMA2axis start
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("Press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("Download the partial bit file of the Laplacian filter and press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 0: Turn decoupling off

    // laplacian filter start
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR+XLAP_FILTER_AXIS_CONTROL_ADDR_ROW_DATA, (u32)VERTICAL_LINES);
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR+XLAP_FILTER_AXIS_CONTROL_ADDR_COL_DATA, (u32)HORIZONTAL_PIXELS);
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR, (u32)0x81);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("Press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("Download the partial bit file of the Sobel filter and press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 0: Turn decoupling off

    // sobel filter start
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR+XSOBEL_FILTER_AXIS_CONTROL_ADDR_ROW_DATA, (u32)VERTICAL_LINES);
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR+XSOBEL_FILTER_AXIS_CONTROL_ADDR_COL_DATA, (u32)HORIZONTAL_PIXELS);
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR, (u32)0x81);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    return(0);
}


Vitis の Explorer 画面で DFX_filter_test_system を選択し、Run ボタンをクリックする。
gtkterm の画面に”Press the key”と表示された。
この状態では通常のカメラ画像が表示されている。
DFX2_123_210822.jpg

gtkterm 画面で何かのキーを押した。
”Download the partial bit file of the Laplacian filter and press the key.”が表示された。
DFX2_117_210821.png

Vivado で PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target -> Auto Connect を選択する。
HARDWARE MANAGER が表示された。
Program device をクリックする。
DFX2_121_210821.png

DFX_filter_test_i_filter_lap_filter_axis_inst_0_partial.bit を指定してコンフィギュレーションした。
DFX2_118_210821.png

gtkterm で何かキーを押すと、ラプラシアン・フィルタ画像がディスプレイに表示された。
ただしスタート位置が間違っている。
DFX2_124_210822.jpg

もう一度、何かキーを押すと、”Download the partial bit file of the Sobel filter and press the key.”が表示された。
DFX2_119_210821.png

Vivado で DFX_filter_test_i_filter_sobel_filter_axis_inst_0_partial.bit をコンフィギュレーションした。
DFX2_120_210819.png

何かキーを押すと、ソーベル・フィルタの画面がディスプレイに表示された。
これもスタート位置が間違っている。
DFX2_125_210822.jpg

これで、手動での DFX はうまく行ったと思う。
ディスプレイ表示にはバグというかビットマップ・ディスプレイ・コントローラの仕様による不具合はあったが。。。
  1. 2021年08月22日 07:41 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


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

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