// fifo_test.cpp
// 2016/09/26 by marsee
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include "fifo_test.h"
int fifo_test(hls::stream<ap_uint<32> >& ins, hls::stream<ap_uint<32> >& outs){
#pragma HLS DATAFLOW
ap_uint<32> buf[HORIZONTAL_PIXEL_WIDTH];
ap_uint<32> ind, outd;
int i, j;
input : for(i=0; i<HORIZONTAL_PIXEL_WIDTH; i++){
#pragma HLS PIPELINE II=1
ins >> buf[i];
}
output : for(j=0; j<HORIZONTAL_PIXEL_WIDTH; j++){
#pragma HLS PIPELINE II=1
while(i <= j) ; // i よりも j が等しいか大きい場合はwait
outs << buf[j];
}
return 0;
}
// fifo_test.h
// 2016/09/26 by marsee
//
#ifndef __FIFO_TEST_H__
#define __FIFO_TEST_H__
//#define HORIZONTAL_PIXEL_WIDTH 800
//#define VERTICAL_PIXEL_WIDTH 600
#define HORIZONTAL_PIXEL_WIDTH 640
#define VERTICAL_PIXEL_WIDTH 480
#endif
// fifo_test.cpp
// 2016/09/26 by marsee
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include "fifo_test.h"
int fifo_test(hls::stream<ap_uint<32> >& ins, hls::stream<ap_uint<32> >& outs){
ap_uint<32> buf[HORIZONTAL_PIXEL_WIDTH];
ap_uint<32> ind, outd;
int i, j;
input : for(i=0; i<HORIZONTAL_PIXEL_WIDTH; i++){
ins >> buf[i];
}
output : for(j=0; j<HORIZONTAL_PIXEL_WIDTH; j++){
while(i <= j) ; // i よりも j が等しいか大きい場合はwait
outs << buf[j];
}
return 0;
}
// fifo_test_tb.cpp
// 2016/09/26 by marsee
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include "fifo_test.h"
#include "bmp_header.h"
int fifo_test(hls::stream<ap_uint<32> >& ins, hls::stream<ap_uint<32> >& outs);
#define BMP_FILE_NAME "road_1.bmp"
int main()
{
using namespace std;
hls::stream<ap_uint<32> > ins;
hls::stream<ap_uint<32> > outs;
ap_uint<32> pix, result;
BITMAPFILEHEADER bmpfhr; // BMPファイルのファイルヘッダ(for Read)
BITMAPINFOHEADER bmpihr; // BMPファイルのINFOヘッダ(for Read)
FILE *fbmpr, *fbmpw;
ap_uint<32> *rd_bmp, *result_copy;
int blue, green, red;
if ((fbmpr = fopen(BMP_FILE_NAME, "rb")) == NULL){ // BMP をオープン
fprintf(stderr, "Can't open test.bmp by binary read mode\n");
exit(1);
}
// bmpヘッダの読み出し
fread(&bmpfhr.bfType, sizeof(char), 2, fbmpr);
fread(&bmpfhr.bfSize, sizeof(long), 1, fbmpr);
fread(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpr);
fread(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpr);
fread(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpr);
fread(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpr);
// ピクセルを入れるメモリをアロケートする
if ((rd_bmp =(ap_uint<32> *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
fprintf(stderr, "Can't allocate rd_bmp memory\n");
exit(1);
}
if ((result_copy =(ap_uint<32> *)malloc(sizeof(int) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
fprintf(stderr, "Can't allocate result_copy memory\n");
exit(1);
}
// rd_bmp にBMPのピクセルを代入。その際に、行を逆転する必要がある
for (int y=0; y<bmpihr.biHeight; y++){
for (int x=0; x<bmpihr.biWidth; x++){
blue = fgetc(fbmpr);
green = fgetc(fbmpr);
red = fgetc(fbmpr);
rd_bmp[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] = (blue & 0xff) | ((green & 0xff)<<8) | ((red & 0xff)<<16);
}
}
fclose(fbmpr);
for(int j=0; j < bmpihr.biHeight; j++){
for(int i=0; i < bmpihr.biWidth; i++){
pix = rd_bmp[(j*bmpihr.biWidth)+i];
ins << pix;
}
}
// 1行容量の fifo_test を呼び出しながら、malloc 領域に書き込む
for(int j=0; j < bmpihr.biHeight; j++){
fifo_test(ins, outs);
for(int i=0; i < bmpihr.biWidth; i++){
outs >> result;
result_copy[(j*bmpihr.biWidth)+i] = result;
}
}
// ハードウェアのラプラシアンフィルタの結果を result_copy.bmp へ出力する
if ((fbmpw=fopen("result_copy.bmp", "wb")) == NULL){
fprintf(stderr, "Can't open result_copy.bmp by binary write mode\n");
exit(1);
}
// BMPファイルヘッダの書き込み
fwrite(&bmpfhr.bfType, sizeof(char), 2, fbmpw);
fwrite(&bmpfhr.bfSize, sizeof(long), 1, fbmpw);
fwrite(&bmpfhr.bfReserved1, sizeof(short), 1, fbmpw);
fwrite(&bmpfhr.bfReserved2, sizeof(short), 1, fbmpw);
fwrite(&bmpfhr.bfOffBits, sizeof(long), 1, fbmpw);
fwrite(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpw);
// RGB データの書き込み、逆順にする
for (int y=0; y<bmpihr.biHeight; y++){
for (int x=0; x<bmpihr.biWidth; x++){
blue = result_copy[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] & 0xff;
green = (result_copy[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] >> 8) & 0xff;
red = (result_copy[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x]>>16) & 0xff;
fputc(blue, fbmpw);
fputc(green, fbmpw);
fputc(red, fbmpw);
}
}
fclose(fbmpw);
free(rd_bmp);
free(result_copy);
}
// cam_disp3_axis.c
// 2015/12/02 by marsee
//
// Refered to Xilinx\SDK\2015.1\data\embeddedsw\XilinxProcessorIPLib\drivers\axivdma_v5_1\doc\html\api
// Refered to https://github.com/elitezhe/Atyls-VDMA-one-in-one-out/blob/master/SDK/colorbar/src/helloworld.c
// Refered to http://www.xilinx.com/support/documentation/ip_documentation/axi_vdma/v6_2/pg020_axi_vdma.pdf
// Refered to http://forums.xilinx.com/t5/Embedded-Processor-System-Design/Axi-VDMA-on-Digilent-Atlys/td-p/297019/page/2
//
// normal camera out
//
#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"
#include "xdmaw4gabor.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(){
XDmaw4gabor xdma4g;
// 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);
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, 0xf0, 0x1); // Changed regster map to IFP page 1
cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0x97, 0x20); // RGB Mode, RGB565
mt9d111_axi_lites[1] = 0; // One_shot_mode is disabled
return(0);
}
/* * gabor_disp.c * * Created on: 2016/09/23 * Author: marsee */
#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xparameters.h"
#include "xgabor_filter_lh.h"
#include "xdmaw4gabor.h"
#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)
int main(){
XGabor_filter_lh gabf;
XDmaw4gabor xdma4g;
XGabor_filter_lh_Initialize(&gabf, 0);
XGabor_filter_lh_Start(&gabf);
XGabor_filter_lh_EnableAutoRestart(&gabf);
// 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), 0x80000000);
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x44), 0x80000000); // disable
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x48), 0x0); // 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), 0x2);
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR), 0x2); // Commit registers
// DMAW4Gabor Address set
XDmaw4gabor_Initialize(&xdma4g, 0);
XDmaw4gabor_Set_frame_buffer0(&xdma4g, FRAME_BUFFER_ADDRESS);
XDmaw4gabor_Set_frame_buffer1(&xdma4g, FRAME_BUFFER_ADDRESS+ALL_DISP_ADDRESS);
// Bitmap display Controller Address set
volatile unsigned int *bmdc0_axi_lites;
volatile unsigned int *bmdc1_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;
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
return 0;
}
/* * gabor_right.c * * Created on: 2016/09/23 * Author: marsee */
#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xparameters.h"
#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)
int main(){
volatile unsigned int *bmdc0_axi_lites;
volatile unsigned int *bmdc1_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;
bmdc0_axi_lites[0] = (volatile unsigned int)(FRAME_BUFFER_ADDRESS+ALL_DISP_ADDRESS); // Bitmap Display Controller 0 start
bmdc1_axi_lites[0] = (volatile unsigned int)(FRAME_BUFFER_ADDRESS+ALL_DISP_ADDRESS); // Bitmap Display Controller 1 start
return 0;
}
/* * gabor_left.c * * Created on: 2016/09/23 * Author: marsee */
#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xparameters.h"
#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)
int main(){
volatile unsigned int *bmdc0_axi_lites;
volatile unsigned int *bmdc1_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;
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
return 0;
}
// dmaw4gabor.h
// 2016/09/20 by marsee
//
#ifndef __DMA_WRITE_H__
#define __DMA_WRITE_H__
//#define HORIZONTAL_PIXEL_WIDTH 800
//#define VERTICAL_PIXEL_WIDTH 600
#define HORIZONTAL_PIXEL_WIDTH 64
#define VERTICAL_PIXEL_WIDTH 48
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define MAX_FRAME_NUMBER 2
#endif
// dmaw4gabor.cpp
// 2016/09/20 by marsee
//
// frame_buffer0, frame_buffer1、2つのフレームバッファ
// if (RorL == 0) Left Gabor filter
// if (RorL == 1) Right Gabor filter
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include "dmaw4gabor.h"
int dmaw4gabor(hls::stream<ap_axis<32,1,1,1> >& ins, volatile int *out,
unsigned int frame_buffer0, unsigned int frame_buffer1,
volatile ap_uint<1> & RorL){
#pragma HLS INTERFACE ap_none port=RorL
#pragma HLS INTERFACE s_axilite port=frame_buffer0
#pragma HLS INTERFACE s_axilite port=frame_buffer1
#pragma HLS INTERFACE m_axi depth=5000000 port=out offset=off
#pragma HLS INTERFACE axis port=ins
#pragma HLS INTERFACE s_axilite port=return
ap_axis<32,1,1,1> pix;
int dma_index;
for (int i=0; i<MAX_FRAME_NUMBER; i++){
switch (i){
case 0 :
dma_index = frame_buffer0/sizeof(int);
break;
default: //case 1 :
dma_index = frame_buffer1/sizeof(int);
break;
}
RorL = i;
do { // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
ins >> pix;
} while(pix.user == 0);
for (int y=0; y<VERTICAL_PIXEL_WIDTH; y++){
for (int x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS PIPELINE II=1
if (!(x==0 && y==0)) // 最初の入力はすでに入力されている
ins >> pix; // AXI4-Stream からの入力
out[dma_index+(y*HORIZONTAL_PIXEL_WIDTH)+x] = pix.data;
}
}
}
return 0;
}
// DMA_Read_addr.cpp
// 2016/07/13 by marsee
//
// frame_buffer0, frame_buffer1, frame_buffer2 には3つのフレームバッファのアドレスを入れる
// mode = 0 : DMA Write IP の active_frame を見て、その1つ前のフレームをDMA Readするモード(DMA_WRITE_MODE)
// mode = 1 : フリーラン モード(FREE_RUN_MODE)
// 2016/09/18 : memcpy を使用
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include "DMA_Read.h"
int DMA_Read_addr(volatile int *in, hls::stream<ap_axis<32,1,1,1> >& outs,
unsigned int frame_buffer0, unsigned int frame_buffer1,
unsigned int frame_buffer2, ap_uint<2> & active_frame,
ap_uint<1> mode){
#pragma HLS INTERFACE s_axilite port=mode
#pragma HLS INTERFACE ap_none port=active_frame
#pragma HLS INTERFACE s_axilite port=frame_buffer0
#pragma HLS INTERFACE s_axilite port=frame_buffer1
#pragma HLS INTERFACE s_axilite port=frame_buffer2
#pragma HLS INTERFACE m_axi depth=5000000 port=in offset=off
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE s_axilite port=return
ap_axis<32,1,1,1> pix;
int dma_index, n;
int buf1[HORIZONTAL_PIXEL_WIDTH/2];
int buf2[HORIZONTAL_PIXEL_WIDTH/2];
for (int i=0; i<MAX_FRAME_NUMBER; i++){
if (mode == DMA_WRITE_MODE)
n = (int)active_frame;
else
n = i;
switch (n){ // 1つ前のフレームバッファを読みだす
case 0 :
dma_index = frame_buffer2/sizeof(int);
break;
case 1 :
dma_index = frame_buffer0/sizeof(int);
break;
case 2 :
dma_index = frame_buffer1/sizeof(int);
break;
default :
dma_index = frame_buffer0/sizeof(int);
break;
}
for (int y=0; y<VERTICAL_PIXEL_WIDTH; y++){
#pragma HLS DATAFLOW
memcpy(buf1, (const int*)(&in[dma_index+(y*HORIZONTAL_PIXEL_WIDTH)]), (HORIZONTAL_PIXEL_WIDTH)*2);
memcpy(buf2, (const int*)(&in[dma_index+(y*HORIZONTAL_PIXEL_WIDTH)+(HORIZONTAL_PIXEL_WIDTH/2)]),
(HORIZONTAL_PIXEL_WIDTH)*2);
for (int x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS PIPELINE II=1
if (x < HORIZONTAL_PIXEL_WIDTH/2)
pix.data = buf1[x];
else
pix.data = buf2[x-HORIZONTAL_PIXEL_WIDTH/2];
if (y==0 && x==0)
pix.user = 1;
else
pix.user = 0;
if (x == (HORIZONTAL_PIXEL_WIDTH-1))
pix.last = 1;
else
pix.last = 0;
outs << pix;
}
}
}
return 0;
}
// DMA_Read.h
// 2016/07/14 by marsee
// 2016/09/18 : BURST_LENGTH を追加
//
#ifndef __DMA_READ_H__
#define __DMA_READ_H__
#define HORIZONTAL_PIXEL_WIDTH 800
#define VERTICAL_PIXEL_WIDTH 600
//#define HORIZONTAL_PIXEL_WIDTH 64
//#define VERTICAL_PIXEL_WIDTH 48
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define MAX_FRAME_NUMBER 3
#define DMA_WRITE_MODE 0
#define FREE_RUN_MODE 1
#define MEMCPY_LENGTH (HORIZONTAL_PIXEL_WIDTH*4)
#endif
で1行分の画像データをRead しようとしたが、これだと、Cコードからの合成で不思議なエラーになってしまう。memcpy(buf1, (const int*)(&in[dma_index+(y*HORIZONTAL_PIXEL_WIDTH)]), (HORIZONTAL_PIXEL_WIDTH)*4);
Instruction does not dominate all uses!
%in_addr = getelementptr inbounds i32* %in, i64 %tmp_12_mid2, !dbg !1886
%in_addr_1_rd_req = call i1 @_ssdm_op_ReadReq.m_axi.i32P(i32* %in_addr, i32 480000), !dbg !1886
Broken module found, compilation aborted!
R6025
- pure virtual function call
// DMA_Read_addr.cpp
// 2016/07/13 by marsee
//
// frame_buffer0, frame_buffer1, frame_buffer2 には3つのフレームバッファのアドレスを入れる
// mode = 0 : DMA Write IP の active_frame を見て、その1つ前のフレームをDMA Readするモード(DMA_WRITE_MODE)
// mode = 1 : フリーラン モード(FREE_RUN_MODE)
// 2016/09/18 : memcpy を使用
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include "DMA_Read.h"
int DMA_Read_addr(volatile int *in, hls::stream<ap_axis<32,1,1,1> >& outs,
unsigned int frame_buffer0, unsigned int frame_buffer1,
unsigned int frame_buffer2, ap_uint<2> & active_frame,
ap_uint<1> mode){
#pragma HLS INTERFACE s_axilite port=mode
#pragma HLS INTERFACE ap_none port=active_frame
#pragma HLS INTERFACE s_axilite port=frame_buffer0
#pragma HLS INTERFACE s_axilite port=frame_buffer1
#pragma HLS INTERFACE s_axilite port=frame_buffer2
#pragma HLS INTERFACE m_axi depth=5000000 port=in offset=off
#pragma HLS INTERFACE axis port=outs
#pragma HLS INTERFACE s_axilite port=return
ap_axis<32,1,1,1> pix;
int dma_index, n;
int buf[HORIZONTAL_PIXEL_WIDTH];
for (int i=0; i<MAX_FRAME_NUMBER; i++){
if (mode == DMA_WRITE_MODE)
n = (int)active_frame;
else
n = i;
switch (n){ // 1つ前のフレームバッファを読みだす
case 0 :
dma_index = frame_buffer2/sizeof(int);
break;
case 1 :
dma_index = frame_buffer0/sizeof(int);
break;
case 2 :
dma_index = frame_buffer1/sizeof(int);
break;
default :
dma_index = frame_buffer0/sizeof(int);
break;
}
for (int y=0; y<VERTICAL_PIXEL_WIDTH; y++){
#pragma HLS DATAFLOW
memcpy(buf, (const int*)(&in[dma_index+(y*HORIZONTAL_PIXEL_WIDTH)]), (HORIZONTAL_PIXEL_WIDTH)*4);
for (int x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
#pragma HLS PIPELINE II=1
pix.data = buf[x];
if (y==0 && x==0)
pix.user = 1;
else
pix.user = 0;
if (x == (HORIZONTAL_PIXEL_WIDTH-1))
pix.last = 1;
else
pix.last = 0;
outs << pix;
}
}
}
return 0;
}
// DMA_Read_test2_tb.v
// 2016/09/15 by marsee
//
module DMA_Read_test2_tb;
wire [31:0]M00_AXI_araddr;
wire [1:0]M00_AXI_arburst;
wire [3:0]M00_AXI_arcache;
wire [7:0]M00_AXI_arlen;
wire [1:0]M00_AXI_arlock;
wire [2:0]M00_AXI_arprot;
wire [3:0]M00_AXI_arqos;
wire M00_AXI_arready;
wire [3:0]M00_AXI_arregion;
wire [2:0]M00_AXI_arsize;
wire M00_AXI_arvalid;
wire [31:0]M00_AXI_awaddr;
wire [1:0]M00_AXI_awburst;
wire [3:0]M00_AXI_awcache;
wire [7:0]M00_AXI_awlen;
wire [1:0]M00_AXI_awlock;
wire [2:0]M00_AXI_awprot;
wire [3:0]M00_AXI_awqos;
wire M00_AXI_awready;
wire [3:0]M00_AXI_awregion;
wire [2:0]M00_AXI_awsize;
wire M00_AXI_awvalid;
wire M00_AXI_bready;
wire [1:0]M00_AXI_bresp;
wire M00_AXI_bvalid;
wire [31:0]M00_AXI_rdata;
wire M00_AXI_rlast;
wire M00_AXI_rready;
wire [1:0]M00_AXI_rresp;
wire M00_AXI_rvalid;
wire [31:0]M00_AXI_wdata;
wire M00_AXI_wlast;
wire M00_AXI_wready;
wire [3:0]M00_AXI_wstrb;
wire M00_AXI_wvalid;
wire [31:0]S00_AXI_araddr;
wire [1:0]S00_AXI_arburst;
wire [3:0]S00_AXI_arcache;
wire [7:0]S00_AXI_arlen;
wire [0:0]S00_AXI_arlock;
wire [2:0]S00_AXI_arprot;
wire [3:0]S00_AXI_arqos;
wire S00_AXI_arready;
wire [3:0]S00_AXI_arregion;
wire [2:0]S00_AXI_arsize;
wire S00_AXI_arvalid;
wire [31:0]S00_AXI_awaddr;
wire [1:0]S00_AXI_awburst;
wire [3:0]S00_AXI_awcache;
wire [7:0]S00_AXI_awlen;
wire [0:0]S00_AXI_awlock;
wire [2:0]S00_AXI_awprot;
wire [3:0]S00_AXI_awqos;
wire S00_AXI_awready;
wire [3:0]S00_AXI_awregion;
wire [2:0]S00_AXI_awsize;
wire S00_AXI_awvalid;
wire S00_AXI_bready;
wire [1:0]S00_AXI_bresp;
wire S00_AXI_bvalid;
wire [31:0]S00_AXI_rdata;
wire S00_AXI_rlast;
wire S00_AXI_rready;
wire [1:0]S00_AXI_rresp;
wire S00_AXI_rvalid;
wire [31:0]S00_AXI_wdata;
wire S00_AXI_wlast;
wire S00_AXI_wready;
wire [3:0]S00_AXI_wstrb;
wire S00_AXI_wvalid;
wire [1:0]active_frame_V;
wire ap_clk;
wire ap_rst_n;
wire interrupt;
wire [31:0]outs_tdata;
wire [0:0]outs_tdest;
wire [0:0]outs_tid;
wire [3:0]outs_tkeep;
wire [0:0]outs_tlast;
wire outs_tready;
wire [3:0]outs_tstrb;
wire [0:0]outs_tuser;
wire outs_tvalid;
DMA_Read_test2_wrapper DMA_Read_test2_wrapper_i(
.M00_AXI_araddr(M00_AXI_araddr),
.M00_AXI_arburst(M00_AXI_arburst),
.M00_AXI_arcache(M00_AXI_arcache),
.M00_AXI_arlen(M00_AXI_arlen),
.M00_AXI_arlock(M00_AXI_arlock),
.M00_AXI_arprot(M00_AXI_arprot),
.M00_AXI_arqos(M00_AXI_arqos),
.M00_AXI_arready(M00_AXI_arready),
.M00_AXI_arregion(M00_AXI_arregion),
.M00_AXI_arsize(M00_AXI_arsize),
.M00_AXI_arvalid(M00_AXI_arvalid),
.M00_AXI_awaddr(M00_AXI_awaddr),
.M00_AXI_awburst(M00_AXI_awburst),
.M00_AXI_awcache(M00_AXI_awcache),
.M00_AXI_awlen(M00_AXI_awlen),
.M00_AXI_awlock(M00_AXI_awlock),
.M00_AXI_awprot(M00_AXI_awprot),
.M00_AXI_awqos(M00_AXI_awqos),
.M00_AXI_awready(M00_AXI_awready),
.M00_AXI_awregion(M00_AXI_awregion),
.M00_AXI_awsize(M00_AXI_awsize),
.M00_AXI_awvalid(M00_AXI_awvalid),
.M00_AXI_bready(M00_AXI_bready),
.M00_AXI_bresp(M00_AXI_bresp),
.M00_AXI_bvalid(M00_AXI_bvalid),
.M00_AXI_rdata(M00_AXI_rdata),
.M00_AXI_rlast(M00_AXI_rlast),
.M00_AXI_rready(M00_AXI_rready),
.M00_AXI_rresp(M00_AXI_rresp),
.M00_AXI_rvalid(M00_AXI_rvalid),
.M00_AXI_wdata(M00_AXI_wdata),
.M00_AXI_wlast(M00_AXI_wlast),
.M00_AXI_wready(M00_AXI_wready),
.M00_AXI_wstrb(M00_AXI_wstrb),
.M00_AXI_wvalid(M00_AXI_wvalid),
.S00_AXI_araddr(S00_AXI_araddr),
.S00_AXI_arburst(S00_AXI_arburst),
.S00_AXI_arcache(S00_AXI_arcache),
.S00_AXI_arlen(S00_AXI_arlen),
.S00_AXI_arlock(S00_AXI_arlock),
.S00_AXI_arprot(S00_AXI_arprot),
.S00_AXI_arqos(S00_AXI_arqos),
.S00_AXI_arready(S00_AXI_arready),
.S00_AXI_arregion(S00_AXI_arregion),
.S00_AXI_arsize(S00_AXI_arsize),
.S00_AXI_arvalid(S00_AXI_arvalid),
.S00_AXI_awaddr(S00_AXI_awaddr),
.S00_AXI_awburst(S00_AXI_awburst),
.S00_AXI_awcache(S00_AXI_awcache),
.S00_AXI_awlen(S00_AXI_awlen),
.S00_AXI_awlock(S00_AXI_awlock),
.S00_AXI_awprot(S00_AXI_awprot),
.S00_AXI_awqos(S00_AXI_awqos),
.S00_AXI_awready(S00_AXI_awready),
.S00_AXI_awregion(S00_AXI_awregion),
.S00_AXI_awsize(S00_AXI_awsize),
.S00_AXI_awvalid(S00_AXI_awvalid),
.S00_AXI_bready(S00_AXI_bready),
.S00_AXI_bresp(S00_AXI_bresp),
.S00_AXI_bvalid(S00_AXI_bvalid),
.S00_AXI_rdata(S00_AXI_rdata),
.S00_AXI_rlast(S00_AXI_rlast),
.S00_AXI_rready(S00_AXI_rready),
.S00_AXI_rresp(S00_AXI_rresp),
.S00_AXI_rvalid(S00_AXI_rvalid),
.S00_AXI_wdata(S00_AXI_wdata),
.S00_AXI_wlast(S00_AXI_wlast),
.S00_AXI_wready(S00_AXI_wready),
.S00_AXI_wstrb(S00_AXI_wstrb),
.S00_AXI_wvalid(S00_AXI_wvalid),
.active_frame_V(active_frame_V),
.ap_clk(ap_clk),
.ap_rst_n(ap_rst_n),
.interrupt(interrupt),
.outs_tdata(outs_tdata),
.outs_tdest(outs_tdest),
.outs_tid(outs_tid),
.outs_tkeep(outs_tkeep),
.outs_tlast(outs_tlast),
.outs_tready(outs_tready),
.outs_tstrb(outs_tstrb),
.outs_tuser(outs_tuser),
.outs_tvalid(outs_tvalid)
);
assign outs_tready = 1'b1;
reg_write_read reg_write_read_i (
.ap_clk(ap_clk),
.ap_rst_n(ap_rst_n),
.ap_start(1'b1),
.ap_done(),
.ap_idle(),
.ap_ready(),
.m_axi_axi4m_AWVALID(S00_AXI_awvalid),
.m_axi_axi4m_AWREADY(S00_AXI_awready),
.m_axi_axi4m_AWADDR(S00_AXI_awaddr),
.m_axi_axi4m_AWID(),
.m_axi_axi4m_AWLEN(S00_AXI_awlen),
.m_axi_axi4m_AWSIZE(S00_AXI_awsize),
.m_axi_axi4m_AWBURST(S00_AXI_awburst),
.m_axi_axi4m_AWLOCK(S00_AXI_awlock),
.m_axi_axi4m_AWCACHE(S00_AXI_awcache),
.m_axi_axi4m_AWPROT(S00_AXI_awprot),
.m_axi_axi4m_AWQOS(S00_AXI_awqos),
.m_axi_axi4m_AWREGION(S00_AXI_awregion),
.m_axi_axi4m_AWUSER(),
.m_axi_axi4m_WVALID(S00_AXI_wvalid),
.m_axi_axi4m_WREADY(S00_AXI_wready),
.m_axi_axi4m_WDATA(S00_AXI_wdata),
.m_axi_axi4m_WSTRB(S00_AXI_wstrb),
.m_axi_axi4m_WLAST(S00_AXI_wlast),
.m_axi_axi4m_WID(),
.m_axi_axi4m_WUSER(),
.m_axi_axi4m_ARVALID(S00_AXI_arvalid),
.m_axi_axi4m_ARREADY(S00_AXI_arready),
.m_axi_axi4m_ARADDR(S00_AXI_araddr),
.m_axi_axi4m_ARID(),
.m_axi_axi4m_ARLEN(S00_AXI_arlen),
.m_axi_axi4m_ARSIZE(S00_AXI_arsize),
.m_axi_axi4m_ARBURST(S00_AXI_arburst),
.m_axi_axi4m_ARLOCK(S00_AXI_arlock),
.m_axi_axi4m_ARCACHE(S00_AXI_arcache),
.m_axi_axi4m_ARPROT(S00_AXI_arprot),
.m_axi_axi4m_ARQOS(S00_AXI_arqos),
.m_axi_axi4m_ARREGION(S00_AXI_arregion),
.m_axi_axi4m_ARUSER(),
.m_axi_axi4m_RVALID(S00_AXI_rvalid),
.m_axi_axi4m_RREADY(S00_AXI_rready),
.m_axi_axi4m_RDATA(S00_AXI_rdata),
.m_axi_axi4m_RLAST(S00_AXI_rlast),
.m_axi_axi4m_RID(),
.m_axi_axi4m_RUSER(),
.m_axi_axi4m_RRESP(S00_AXI_rresp),
.m_axi_axi4m_BVALID(S00_AXI_bvalid),
.m_axi_axi4m_BREADY(S00_AXI_bready),
.m_axi_axi4m_BRESP(S00_AXI_bresp),
.m_axi_axi4m_BID(1'b0),
.m_axi_axi4m_BUSER(1'b0),
.dummy_out(),
.ap_return()
);
axi_slave_bfm #(
.READ_DATA_IS_INCREMENT(1'b1)
) axi_slave_bfm_i (
.ACLK(ap_clk),
.ARESETN(ap_rst_n),
.S_AXI_AWID(1'b0),
.S_AXI_AWADDR(M00_AXI_awaddr),
.S_AXI_AWLEN(M00_AXI_awlen),
.S_AXI_AWSIZE(M00_AXI_awsize),
.S_AXI_AWBURST(M00_AXI_awburst),
.S_AXI_AWLOCK(M00_AXI_awlock),
.S_AXI_AWCACHE(M00_AXI_awcache),
.S_AXI_AWPROT(M00_AXI_awprot),
.S_AXI_AWQOS(M00_AXI_awqos),
.S_AXI_AWUSER(1'b0),
.S_AXI_AWVALID(M00_AXI_awvalid),
.S_AXI_AWREADY(M00_AXI_awready),
.S_AXI_WDATA(M00_AXI_wdata),
.S_AXI_WSTRB(M00_AXI_wstrb),
.S_AXI_WLAST(M00_AXI_wlast),
.S_AXI_WUSER(1'b0),
.S_AXI_WVALID(M00_AXI_wvalid),
.S_AXI_WREADY(M00_AXI_wready),
.S_AXI_BID(),
.S_AXI_BRESP(M00_AXI_bresp),
.S_AXI_BUSER(),
.S_AXI_BREADY(M00_AXI_bready),
.S_AXI_ARID(1'b0),
.S_AXI_ARADDR(M00_AXI_araddr),
.S_AXI_ARLEN(M00_AXI_arlen),
.S_AXI_ARSIZE(M00_AXI_arsize),
.S_AXI_ARBURST(M00_AXI_arburst),
.S_AXI_ARLOCK(M00_AXI_arlock),
.S_AXI_ARCACHE(M00_AXI_arcache),
.S_AXI_ARPROT(M00_AXI_arprot),
.S_AXI_ARQOS(M00_AXI_arqos),
.S_AXI_ARUSER(1'b0),
.S_AXI_ARVALID(M00_AXI_arvalid),
.S_AXI_ARREADY(M00_AXI_arready),
.S_AXI_RID(),
.S_AXI_RDATA(M00_AXI_rdata),
.S_AXI_RRESP(M00_AXI_rresp),
.S_AXI_RLAST(M00_AXI_rlast),
.S_AXI_RUSER(),
.S_AXI_RVALID(M00_AXI_rvalid),
.S_AXI_RREADY(M00_AXI_rready)
);
// sys_clock
clk_gen #(
.CLK_PERIOD(100), // 10.0nsec, 100MHz
.CLK_DUTY_CYCLE(0.5),
.CLK_OFFSET(0),
.START_STATE(1'b0)
) sys_clock_i (
.clk_out(ap_clk)
);
// reset_rtl_n
reset_gen #(
.RESET_STATE(1'b0),
.RESET_TIME(1000) // 100nsec
) RESET2i (
.reset_out(ap_rst_n)
);
endmodule
module clk_gen #(
parameter CLK_PERIOD = 100,
parameter real CLK_DUTY_CYCLE = 0.5,
parameter CLK_OFFSET = 0,
parameter START_STATE = 1'b0 )
(
output reg clk_out
);
begin
initial begin
#CLK_OFFSET;
forever
begin
clk_out = START_STATE;
#(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
#(CLK_PERIOD*CLK_DUTY_CYCLE);
end
end
end
endmodule
module reset_gen #(
parameter RESET_STATE = 1'b1,
parameter RESET_TIME = 100 )
(
output reg reset_out
);
begin
initial begin
reset_out = RESET_STATE;
#RESET_TIME;
reset_out = ~RESET_STATE;
end
end
endmodule
// wl_tracking.cpp
// 2016/09/02 by marsee
//
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <string.h>
#include "xpwm.h"
#include "xmotor_monitor.h"
#define DIR_LEFT_NORMAL 1
#define DIR_LEFT_REVERSE 0
#define DIR_RIGHT_NORMAL 0
#define DIR_RIGHT_REVERSE 1
#define PIXEL_NUM_OF_BYTES 4
#define SVGA_HORIZONTAL_PIXELS 800
#define SVGA_VERTICAL_LINES 600
#define SVGA_ALL_DISP_ADDRESS (SVGA_HORIZONTAL_PIXELS * SVGA_VERTICAL_LINES * PIXEL_NUM_OF_BYTES)
#define GABOR_DETECT_LINE 590
#define GABOR_DETECT_LINE_ADDR (SVGA_HORIZONTAL_PIXELS * GABOR_DETECT_LINE * PIXEL_NUM_OF_BYTES)
#define GABOR_THRESHOLD 5
#define DIST_THRESHOLD 30
#define LEFT_GABOR_EDGE_OVERFLOW 0
#define RIGHT_GABOR_EDGE_OVERFLOW (SVGA_HORIZONTAL_PIXELS/2)
#define DEBUG
//#define MOTOR_OFF
#define MEMCPY
// Gobor filter
//
volatile unsigned *gabor_fil_on(int &fd4){
int fd2, fd3;
volatile unsigned *axis_switch_0, *axis_switch_1;
volatile unsigned *gabor_filter_lh_0;
int gabor_cntrl;
// axis_switch_0 (UIO2)
fd2 = open("/dev/uio2", O_RDWR); // axis_switch_0 interface AXI4 Lite Slave
if (fd2 < 1){
fprintf(stderr, "/dev/uio2 (axis_switch_0) open error\n");
exit(-1);
}
axis_switch_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd2, 0);
if (!axis_switch_0){
fprintf(stderr, "axis_switch_0 mmap error\n");
exit(-1);
}
// axis_switch_1 (UIO3)
fd3 = open("/dev/uio3", O_RDWR); // axis_switch_1 interface AXI4 Lite Slave
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 (axis_switch_1) open error\n");
exit(-1);
}
axis_switch_1 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!axis_switch_1){
fprintf(stderr, "axis_switch_1 mmap error\n");
exit(-1);
}
// gabor_filter_lh_0 (UIo14)
fd4 = open("/dev/uio14", O_RDWR); // gabor_filter_lh_0 interface AXI4 Lite Slave
if (fd4 < 1){
fprintf(stderr, "/dev/uio14 (gabor_filter_lh_0) open error\n");
exit(-1);
}
gabor_filter_lh_0 = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd4, 0);
if (!gabor_filter_lh_0){
fprintf(stderr, "lap_filter_axis_0 mmap error\n");
exit(-1);
}
// axis_switch_1, 1to2 ,Select M01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_1[16] = 0x80000000; // 0x40 = 0x80000000; disable
axis_switch_1[17] = 0x80000000; // 0x44 = 0x80000000; disable
axis_switch_1[18] = 0; // 0x48 = 0;
axis_switch_1[0] = 0x2; // 0x0 = 2; Commit registers
// gabor filter AXIS Start
gabor_filter_lh_0[6] = 0; // left parameter
gabor_cntrl = gabor_filter_lh_0[0] & 0x80; // Auto Restart bit
gabor_filter_lh_0[0] = gabor_cntrl | 0x01; // Start bit set
gabor_filter_lh_0[0] = 0x80; // Auto Restart bit set
// axis_switch_0, 2to1, Select S01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
axis_switch_0[16] = 0x2; // 0x40 = 0x2;
axis_switch_0[0] = 0x2; // 0x0 = 2; Commit registers
munmap((void *)axis_switch_0, 0x10000);
munmap((void *)axis_switch_1, 0x10000);
close(fd2);
close(fd3);
return(gabor_filter_lh_0);
}
int search_gabor_edge(unsigned int start_addr, unsigned int number, int threshold){
volatile int *imgaddr, *endaddr;
int i;
imgaddr = (volatile int *)start_addr;
for (i=0; i<number; i++){
int c=imgaddr[i] & 0xff;
//printf("%d\n",c);
if (c >= threshold){
break;
}
}
return(i);
}
// Motor
//
void motor_settings(XPwm *motorLp, XPwm *motorRp){
XPwm_DisableAutoRestart(motorLp);
while(!XPwm_IsIdle(motorLp)) ;
XPwm_Start(motorLp);
XPwm_EnableAutoRestart(motorLp);
XPwm_DisableAutoRestart(motorRp);
while(!XPwm_IsIdle(motorRp)) ;
XPwm_Start(motorRp);
XPwm_EnableAutoRestart(motorRp);
}
void Stopped_Zybot(XPwm *motorLp, XPwm *motorRp){
XPwm_Set_sw_late_V(motorLp, 0);
XPwm_Set_sw_late_V(motorRp, 0);
}
void motor_initialize(XPwm &motorL, XPwm &motorR, XMotor_monitor &mmL, XMotor_monitor &mmR){
XPwm *motorLp, *motorRp;
XMotor_monitor *mmLp, *mmRp;
motorLp = &motorL;
motorRp = &motorR;
mmLp = &mmL;
mmRp = &mmR;
// Initialization of motor
if (XPwm_Initialize(motorLp, "pwm_0") != XST_SUCCESS){
fprintf(stderr,"pwm_0 (Left) open error\n");
exit(-1);
}
if (XPwm_Initialize(motorRp, "pwm_1") != XST_SUCCESS){
fprintf(stderr,"pwm_1 (Right) open error\n");
exit(-1);
}
// Initialization of motor monitor
if (XMotor_monitor_Initialize(mmLp, "motor_monitor_0") != XST_SUCCESS){
fprintf(stderr,"motor_monitor_0 (Left) open error\n");
exit(-1);
}
if (XMotor_monitor_Initialize(mmRp, "motor_monitor_1") != XST_SUCCESS){
fprintf(stderr,"motor_monitor_1 (Right) open error\n");
exit(-1);
}
// The Motors is rotated in the forward direction.
XPwm_Set_sw_late_V(motorLp, 0);
XPwm_Set_dir_V(motorLp, 1);
XPwm_Set_sw_late_V(motorRp, 0);
XPwm_Set_dir_V(motorRp, 0);
motor_settings(motorLp, motorRp);
}
int main(){
int fd4;
volatile unsigned *gabor_filter_lh_0;
XPwm motorL, motorR;
XMotor_monitor mmL, mmR;
unsigned char attr[1024];
unsigned long phys_addr;
int left_wl_edge, right_wl_edge;
// Gabor filter Initialize
gabor_filter_lh_0 = gabor_fil_on(fd4);
// Motor Initialize
motor_initialize(motorL, motorR, mmL, mmR);
// udmabuf0
int fdf = open("/dev/udmabuf0", O_RDWR | O_SYNC); // frame_buffer, The cache is disabled.
if (fdf == -1){
fprintf(stderr, "/dev/udmabuf0 open error\n");
exit(-1);
}
volatile unsigned *frame_buffer = (volatile unsigned *)mmap(NULL, 3*SVGA_ALL_DISP_ADDRESS, PROT_READ|PROT_WRITE, MAP_SHARED, fdf, 0);
if (!frame_buffer){
fprintf(stderr, "frame_buffer mmap error\n");
exit(-1);
}
// phys_addr of udmabuf0
int fdp = open("/sys/devices/virtual/udmabuf/udmabuf0/phys_addr", O_RDONLY);
if (fdp == -1){
fprintf(stderr, "/sys/devices/virtual/udmabuf/udmabuf0/phys_addr open error\n");
exit(-1);
}
read(fdp, attr, 1024);
sscanf((const char *)attr, "%lx", &phys_addr);
close(fdp);
printf("phys_addr = %x\n", (unsigned int)phys_addr);
// main loop
printf("White line Tracking start. \n");
while(1){
// Gabor filter for left white line
gabor_filter_lh_0[6] = 0; // left parameter
usleep(250000); // Wait 67 ms
left_wl_edge = SVGA_HORIZONTAL_PIXELS/2 - search_gabor_edge(
(unsigned int)frame_buffer+GABOR_DETECT_LINE_ADDR, SVGA_HORIZONTAL_PIXELS/2, GABOR_THRESHOLD);
#ifdef MEMCPY
memcpy((unsigned int *)((unsigned int)frame_buffer+SVGA_ALL_DISP_ADDRESS), (unsigned int *)frame_buffer,
SVGA_ALL_DISP_ADDRESS);
#endif
// Gabor filter for right white line
gabor_filter_lh_0[6] = 1; // right parameter
usleep(250000); // Wait 67 ms
right_wl_edge = search_gabor_edge(
(unsigned int)frame_buffer+GABOR_DETECT_LINE_ADDR+(SVGA_HORIZONTAL_PIXELS/2)*PIXEL_NUM_OF_BYTES,
SVGA_HORIZONTAL_PIXELS/2, GABOR_THRESHOLD);
#ifdef MEMCPY
memcpy((unsigned int *)((unsigned int)frame_buffer+2*SVGA_ALL_DISP_ADDRESS), (unsigned int *)frame_buffer,
SVGA_ALL_DISP_ADDRESS);
#endif
#ifdef DEBUG
printf("left_wl_edge = %d, right_wl_edge = %d\n", left_wl_edge, right_wl_edge);
#endif
if (left_wl_edge == LEFT_GABOR_EDGE_OVERFLOW){
#ifndef MOTOR_OFF
XPwm_Set_sw_late_V(&motorL, 5);
XPwm_Set_sw_late_V(&motorR, 35);
#endif
#ifdef DEBUG
printf("Left gabor edge is overflow\n");
#endif
} else if (right_wl_edge == RIGHT_GABOR_EDGE_OVERFLOW){
#ifndef MOTOR_OFF
XPwm_Set_sw_late_V(&motorL, 35);
XPwm_Set_sw_late_V(&motorR, 5);
#endif
#ifdef DEBUG
printf("Right gabar edge is overflow\n");
#endif
} else if ((right_wl_edge - left_wl_edge) > DIST_THRESHOLD){
#ifndef MOTOR_OFF
XPwm_Set_sw_late_V(&motorL, 25);
XPwm_Set_sw_late_V(&motorR, 15);
#endif
#ifdef DEBUG
printf("Right turn\n");
#endif
} else if ((right_wl_edge - left_wl_edge) < -DIST_THRESHOLD){
#ifndef MOTOR_OFF
XPwm_Set_sw_late_V(&motorL, 15);
XPwm_Set_sw_late_V(&motorR, 25);
#endif
#ifdef DEBUG
printf("Left turn\n");
#endif
} else if (abs(right_wl_edge - left_wl_edge) <= DIST_THRESHOLD){
#ifndef MOTOR_OFF
XPwm_Set_sw_late_V(&motorL, 20);
XPwm_Set_sw_late_V(&motorR, 20);
#endif
#ifdef DEBUG
printf("Go straight\n");
#endif
}
}
}
reg_write_read_reg_0_rom.dat : Write - 0, Read - 1
reg_write_read_reg_1_rom.dat : Delay、単位はクロック数
reg_write_read_reg_2_rom.dat : アドレス、16進数
reg_write_read_reg_3_rom.dat : データ、16進数
R/W Delay Address value
0 0 0x44A00018 0x10000000
0 0 0x44A00020 0x10000000
0 0 0x44A00028 0x10000000
0 0 0x44A00030 0x00000000
0 0 0x44A00000 0x00000001
Vivado HLS では、 合成が実行 された と きに macro __SYNTHESIS__ が定義されます。 これによ り 、 __SYNTHESIS__
macro を使用し て、 デザ イ ンか ら合成不可能な コー ド を削除でき る よ う にな り ます。
// DMA_Write.h
// 2016/07/10 by marsee
// 2016/09/09 __SYNTHESIS__を使うように修正
//
#ifndef __DMA_WRITE_H__
#define __DMA_WRITE_H__
#ifdef __SYNTHESIS__
#define HORIZONTAL_PIXEL_WIDTH 800
#define VERTICAL_PIXEL_WIDTH 600
#else
#define HORIZONTAL_PIXEL_WIDTH 64
#define VERTICAL_PIXEL_WIDTH 48
#endif
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define MAX_FRAME_NUMBER 3
#endif
// cam_disp3_axis.c
// 2016/09/03 by marsee
//
// Refered to Xilinx\SDK\2015.1\data\embeddedsw\XilinxProcessorIPLib\drivers\axivdma_v5_1\doc\html\api
// Refered to https://github.com/elitezhe/Atyls-VDMA-one-in-one-out/blob/master/SDK/colorbar/src/helloworld.c
// Refered to http://www.xilinx.com/support/documentation/ip_documentation/axi_vdma/v6_2/pg020_axi_vdma.pdf
// Refered to http://forums.xilinx.com/t5/Embedded-Processor-System-Design/Axi-VDMA-on-Digilent-Atlys/td-p/297019/page/2
//
// normal camera out
//
#include <stdio.h>
#include <stdlib.h>
#include "xil_io.h"
#include "xparameters.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 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(){
XDma_write dmaw;
// 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), 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
// Initialization of DMA Write
if (XDma_write_Initialize(&dmaw, 0) != XST_SUCCESS){
fprintf(stderr, "DMA Write IP open error");
exit(-1);
}
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);
while(!XDma_write_IsIdle(&dmaw));
XDma_write_Start(&dmaw);
XDma_write_EnableAutoRestart(&dmaw);
// 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, 0xf0, 0x1); // Changed regster map to IFP page 1
cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0x97, 0x20); // RGB Mode, RGB565
mt9d111_axi_lites[1] = 0; // One_shot_mode is disabled
return(0);
}
最初の白線検出、走行プログラム
./cam_disp_vdma でカメラ画像を表示する。
ガボール・フィルタを表示する。
左白線表示にして、67ms(15fps) Waitする。
左白線位置を検出する。(左白線用ガボールフィルタの画像の下 10ライン、つまり590ライン目画面の左端から半分まで走査する)
右白線表示にして、67ms(15fps) Waitする。
右白線位置を検出する。(右白線用ガボールフィルタの画像の下 10ライン、つまり590ライン目画面の半分から右端まで走査する)
左白線位置(左白線エッジから画像中央)と右白線位置(画像中央から右白線エッジ)を比較する。
|右白線位置-左白線位置| <= 10 : 左モーターPWM = 30%, 右モーターPWM = 30%
右白線位置が未検出 : 左モーターPWM = 40%, 右モーターPWM = 30%
左白線位置が未検出 : 左モーターPWM = 30%, 右モーターPWM = 40%
右白線位置 - 左白線位置 > +10 : 左モーターPWM = 35%, 右モーターPWM = 30%
右白線位置 - 左白線位置 < -10 : 左モーターPWM = 30%, 右モーターPWM = 35%
ガボール・フィルタのベースのRGB 値はどれも 0 なので、白線のエッジのスレッショルドはどれか1つの色が 50 になった時とする。
Compiling ../../../Gabor_filter_lh_2_tb.cpp in debug mode
Compiling ../../../Gabor_filter_lh_2.cpp in debug mode
Generating csim.exe
outs
ERROR HW and SW results mismatch i = 557, j = 73, HW = 00171717, SW = 00141414
ERROR HW and SW results mismatch i = 419, j = 88, HW = 00171717, SW = 00141414
ERROR HW and SW results mismatch i = 419, j = 92, HW = 00131313, SW = 00101010
ERROR HW and SW results mismatch i = 405, j = 100, HW = 003e3e3e, SW = 003b3b3b
ERROR HW and SW results mismatch i = 426, j = 106, HW = 00121212, SW = 000f0f0f
ERROR HW and SW results mismatch i = 486, j = 119, HW = 00171717, SW = 00141414
ERROR HW and SW results mismatch i = 235, j = 120, HW = 001b1b1b, SW = 00181818
ERROR HW and SW results mismatch i = 437, j = 120, HW = 00e1e1e1, SW = 00dedede
ERROR HW and SW results mismatch i = 441, j = 120, HW = 00141414, SW = 00111111
ERROR HW and SW results mismatch i = 235, j = 121, HW = 00141414, SW = 00111111
ERROR HW and SW results mismatch i = 425, j = 124, HW = 00a9a9a9, SW = 00a6a6a6
ERROR HW and SW results mismatch i = 425, j = 125, HW = 00e1e1e1, SW = 00dedede
ERROR HW and SW results mismatch i = 252, j = 132, HW = 004e4e4e, SW = 004b4b4b
ERROR HW and SW results mismatch i = 254, j = 133, HW = 00d9d9d9, SW = 00d6d6d6
ERROR HW and SW results mismatch i = 296, j = 145, HW = 00161616, SW = 00131313
ERROR HW and SW results mismatch i = 296, j = 146, HW = 00181818, SW = 00151515
ERROR HW and SW results mismatch i = 135, j = 156, HW = 00dcdcdc, SW = 00d9d9d9
ERROR HW and SW results mismatch i = 137, j = 156, HW = 003f3f3f, SW = 003c3c3c
ERROR HW and SW results mismatch i = 139, j = 157, HW = 00040404, SW = 00010101
ERROR HW and SW results mismatch i = 491, j = 163, HW = 00efefef, SW = 00ececec
ERROR HW and SW results mismatch i = 495, j = 163, HW = 00f3f3f3, SW = 00f0f0f0
Success HW and SW results match
WARNING: Hls::stream 'hls::stream>.2' contains leftover data, which may result in RTL simulation hanging.
WARNING: Hls::stream 'hls::stream>.1' contains leftover data, which may result in RTL simulation hanging.
INFO: [SIM 1] CSim done with 0 errors.
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | - | - | - | 1 | 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | - |