// laplacian_filter2.c
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/09/16
// 2014/12/04 : ZYBO用Ubuntu Linux のUIO用に変更
// Vivado HLS 2014.4 のプロジェクト http://marsee101.blog19.fc2.com/blog-entry-3102.html
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#define HORIZONTAL_PIXEL_WIDTH 800
#define VERTICAL_PIXEL_WIDTH 600
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS 0x18000000 // Limit 0x18800000, 800*600*4 = 2MBytes * 2
#define LAPLACIAN_FILTER_ADDRESS 0x18200000 // 800*600*4 = 0x1d4c00
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y(int rgb);
int chkhex(char *str);
int main()
{
volatile unsigned int *cam_fb = 0;
volatile unsigned int *lap_fb = 0;
volatile unsigned int *cam_addr;
volatile unsigned int *lap_addr;
int lap_fil_val;
int x, y;
struct timeval start_time, temp1, temp2, end_time;
unsigned int line_buf[3][HORIZONTAL_PIXEL_WIDTH];
int a, b;
int fl, sl, tl;
int fd0, fd3;
unsigned int offset_cam_addr, offset_lap_addr;
unsigned int lap_buf[HORIZONTAL_PIXEL_WIDTH];
volatile unsigned int *cam_fb_addr, *lap_fb_addr;
int line_sel;
volatile unsigned int *bmdc_axi_lites;
volatile unsigned int *frame_buffer;
// gettimeofday(&start_time, NULL); // プログラム起動時の時刻を記録
// frame_buffer にマップする
fd3 = open("/dev/uio3", O_RDWR); // Frame Buffer
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 open error\n");
exit(-1);
}
frame_buffer = (volatile unsigned int *)mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!frame_buffer){
fprintf(stderr, "frame_buffer mmap error\n");
exit(-1);
}
cam_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(VIDEO_BUFFER_START_ADDRESS-CMA_START_ADDRESS));
// ラプラシアンフィルタの結果を入れておくフレーム・バッファ
lap_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(LAPLACIAN_FILTER_ADDRESS-CMA_START_ADDRESS));
offset_cam_addr = (volatile unsigned int)((unsigned int)cam_addr/sizeof(int));
offset_lap_addr = (volatile unsigned int)((unsigned int)lap_addr/sizeof(int));
gettimeofday(&start_time, NULL);
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
fl = (y-1)%3; // 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
sl = y%3; // 2番めのライン
tl = (y+1)%3; // 3番目のライン
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
lap_fil_val = 0;
}else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
lap_fil_val = 0;
}else{
if (x == 1){ // ラインの最初でラインの画素を読み出す
if (y == 1){ // 最初のラインでは3ライン分の画素を読み出す
for (a=0; a<3; a++){ // 3ライン分
cam_fb_addr = (int*)(cam_fb+offset_cam_addr+(a*(HORIZONTAL_PIXEL_WIDTH)));
memcpy(&line_buf[a][0], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
line_buf[a][b] = conv_rgb2y(line_buf[a][b]); // カラーから白黒へ
}
}
} else { // 最初のラインではないので、1ラインだけ読み込む。すでに他の2ラインは読み込まれている
cam_fb_addr = (int*)(cam_fb+offset_cam_addr+((y+1)*(HORIZONTAL_PIXEL_WIDTH)));
memcpy(line_buf[(y+1)%3], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
line_buf[(y+1)%3][b] = conv_rgb2y(line_buf[(y+1)%3][b]); // カラーから白黒へ
}
}
}
lap_fil_val = laplacian_fil(line_buf[fl][x-1], line_buf[fl][x], line_buf[fl][x+1], line_buf[sl][x-1], line_buf[sl][x], line_buf[sl][x+1], line_buf[tl][x-1], line_buf[tl][x], line_buf[tl][x+1]);
}
lap_buf[x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる
}
lap_fb_addr = (int *)(lap_fb+offset_lap_addr+(y*(HORIZONTAL_PIXEL_WIDTH)));
memcpy((void *)lap_fb_addr, (const int*)lap_buf, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
}
gettimeofday(&end_time, NULL);
munmap((void *)frame_buffer, 0x1000000);
// ラプラシアンフィルタ表示画面に切り替え
// Bitmap Display Controller AXI4 Lite Slave (UIO0)
fd0 = open("/dev/uio0", O_RDWR); // bitmap_display_controller axi4 lite
if (fd0 < 1){
fprintf(stderr, "/dev/uio0 open error\n");
exit(-1);
}
bmdc_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
if (!bmdc_axi_lites){
fprintf(stderr, "bmdc_axi_lites mmap error\n");
exit(-1);
}
bmdc_axi_lites[0] = (unsigned int)LAPLACIAN_FILTER_ADDRESS; // Bitmap Display Controller start (ラプラシアンフィルタ表示画面のアドレス)
munmap((void *)bmdc_axi_lites, 0x10000);
//gettimeofday(&end_time, NULL);
if (end_time.tv_usec < start_time.tv_usec) {
printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec - 1, 1000000 + end_time.tv_usec - start_time.tv_usec);
}
else {
printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec);
}
return(0);
}
// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y = 0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
int r, g, b, y_f;
int y;
b = rgb & 0xff;
g = (rgb>>8) & 0xff;
r = (rgb>>16) & 0xff;
y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
y = y_f >> 8; // 256で割る
return(y);
}
// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1 8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
int y;
y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
if (y<0)
y = 0;
else if (y>255)
y = 255;
return(y);
}
// 文字列が16進数かを調べる
int chkhex(char *str){
while (*str != '\0'){
if (!isxdigit(*str))
return 0;
str++;
}
return 1;
}
// laplacian_filter3.c
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/09/16
// 2014/12/04 : ZYBO用Ubuntu Linux のUIO用に変更
// Vivado HLS 2014.4 のプロジェクト ZYBO/lap_filter_axim_2014_4を使用したソースコードと同じものを使用する
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>
#define HORIZONTAL_PIXEL_WIDTH 800
#define VERTICAL_PIXEL_WIDTH 600
#define ALL_PIXEL_VALUE (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)
#define CMA_START_ADDRESS 0x17800000
#define VIDEO_BUFFER_START_ADDRESS 0x18000000 // Limit 0x18800000, 800*600*4 = 2MBytes * 2
#define LAPLACIAN_FILTER_ADDRESS 0x18200000 // 800*600*4 = 0x1d4c00
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y(int rgb);
int chkhex(char *str);
int main()
{
volatile unsigned int *cam_fb = 0;
volatile unsigned int *lap_fb = 0;
volatile unsigned int *cam_addr;
volatile unsigned int *lap_addr;
int lap_fil_val;
int x, y;
struct timeval start_time, temp1, temp2, end_time;
unsigned int line_buf[3][HORIZONTAL_PIXEL_WIDTH];
int a, b;
int fl, sl, tl;
int fd0, fd3;
unsigned int offset_cam_addr, offset_lap_addr;
unsigned int lap_buf[HORIZONTAL_PIXEL_WIDTH];
volatile unsigned int *cam_fb_addr, *lap_fb_addr;
int line_sel;
volatile unsigned int *bmdc_axi_lites;
volatile unsigned int *frame_buffer;
// gettimeofday(&start_time, NULL); // プログラム起動時の時刻を記録
// frame_buffer にマップする
fd3 = open("/dev/uio3", O_RDWR); // Frame Buffer
if (fd3 < 1){
fprintf(stderr, "/dev/uio3 open error\n");
exit(-1);
}
frame_buffer = (volatile unsigned int *)mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
if (!frame_buffer){
fprintf(stderr, "frame_buffer mmap error\n");
exit(-1);
}
cam_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(VIDEO_BUFFER_START_ADDRESS-CMA_START_ADDRESS));
// ラプラシアンフィルタの結果を入れておくフレーム・バッファ
lap_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(LAPLACIAN_FILTER_ADDRESS-CMA_START_ADDRESS));
offset_cam_addr = (volatile unsigned int)((unsigned int)cam_addr/sizeof(int));
offset_lap_addr = (volatile unsigned int)((unsigned int)lap_addr/sizeof(int));
gettimeofday(&start_time, NULL);
// RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
for (y=0, line_sel=0; y<VERTICAL_PIXEL_WIDTH; y++){
// 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
switch(line_sel){
case 1 :
fl = 0; sl = 1; tl = 2;
break;
case 2 :
fl = 1; sl = 2; tl = 0;
break;
case 3 :
fl = 2; sl = 0; tl = 1;
break;
default :
fl = 0; sl = 1; tl = 2;
}
//fl = (y-1)%3; // 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
//sl = y%3; // 2番めのライン
//tl = (y+1)%3; // 3番目のライン
for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
lap_fil_val = 0;
}else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
lap_fil_val = 0;
}else{
if (x == 1){ // ラインの最初でラインの画素を読み出す
if (y == 1){ // 最初のラインでは3ライン分の画素を読み出す
for (a=0; a<3; a++){ // 3ライン分
cam_fb_addr = (int*)(cam_fb+offset_cam_addr+(a*(HORIZONTAL_PIXEL_WIDTH)));
memcpy(&line_buf[a][0], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){
#pragma HLS PIPELINE
// ライン
line_buf[a][b] = conv_rgb2y(line_buf[a][b]); // カラーから白黒へ
}
}
} else { // 最初のラインではないので、1ラインだけ読み込む。すでに他の2ラインは読み込まれている
cam_fb_addr = (int*)(cam_fb+offset_cam_addr+((y+1)*(HORIZONTAL_PIXEL_WIDTH)));
memcpy(line_buf[tl], (const int*)cam_fb_addr, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){
#pragma HLS PIPELINE
// ライン
line_buf[tl][b] = conv_rgb2y(line_buf[tl][b]); // カラーから白黒へ
}
}
}
lap_fil_val = laplacian_fil(line_buf[fl][x-1], line_buf[fl][x], line_buf[fl][x+1], line_buf[sl][x-1], line_buf[sl][x], line_buf[sl][x+1], line_buf[tl][x-1], line_buf[tl][x], line_buf[tl][x+1]);
}
lap_buf[x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる
}
lap_fb_addr = (int *)(lap_fb+offset_lap_addr+(y*(HORIZONTAL_PIXEL_WIDTH)));
memcpy((void *)lap_fb_addr, (const int*)lap_buf, HORIZONTAL_PIXEL_WIDTH*sizeof(int));
line_sel++;
if (line_sel > 3){
line_sel = 1;
}
}
gettimeofday(&end_time, NULL);
munmap((void *)frame_buffer, 0x1000000);
// ラプラシアンフィルタ表示画面に切り替え
// Bitmap Display Controller AXI4 Lite Slave (UIO0)
fd0 = open("/dev/uio0", O_RDWR); // bitmap_display_controller axi4 lite
if (fd0 < 1){
fprintf(stderr, "/dev/uio0 open error\n");
exit(-1);
}
bmdc_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
if (!bmdc_axi_lites){
fprintf(stderr, "bmdc_axi_lites mmap error\n");
exit(-1);
}
bmdc_axi_lites[0] = (unsigned int)LAPLACIAN_FILTER_ADDRESS; // Bitmap Display Controller start (ラプラシアンフィルタ表示画面のアドレス)
munmap((void *)bmdc_axi_lites, 0x10000);
//gettimeofday(&end_time, NULL);
if (end_time.tv_usec < start_time.tv_usec) {
printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec - 1, 1000000 + end_time.tv_usec - start_time.tv_usec);
}
else {
printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec);
}
return(0);
}
// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y = 0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
int r, g, b, y_f;
int y;
b = rgb & 0xff;
g = (rgb>>8) & 0xff;
r = (rgb>>16) & 0xff;
y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
y = y_f >> 8; // 256で割る
return(y);
}
// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1 8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
int y;
y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
if (y<0)
y = 0;
else if (y>255)
y = 255;
return(y);
}
// 文字列が16進数かを調べる
int chkhex(char *str){
while (*str != '\0'){
if (!isxdigit(*str))
return 0;
str++;
}
return 1;
}
// lap_fil_on.c
// 2015/06/17 by marsee
//
// Refered to http://japan.xilinx.com/support/documentation/sw_manuals_j/xilinx2014_4/ug902-vivado-high-level-synthesis.pdf
//
#include <stdio.h>
#include "xlap_filter_axis.h"
#include "xparameters.h"
int main(){
XLap_filter_axis Xlap_fil_axis;
XLap_filter_axis_Config *Xlap_fil_axisPtr;
// Look Up the device configuration
Xlap_fil_axisPtr = XLap_filter_axis_LookupConfig(0);
if (!Xlap_fil_axisPtr){
fprintf(stderr, "XLap_filter_axis configuration failed.\n");
return(-1);
}
// Initialize the Device
int Xlap_status = XLap_filter_axis_CfgInitialize(&Xlap_fil_axis, Xlap_fil_axisPtr);
if (Xlap_status != XST_SUCCESS){
fprintf(stderr, "Could not Initialize XLap_filter_axis\n");
return(-1);
}
// axis_switch_1, 1to2 ,Select M01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x40), 0x80000000); // disable
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x44), 0);
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR), 0x2); // Commit registers
// laplacian filter AXIS Start
XLap_filter_axis_Start(&Xlap_fil_axis);
XLap_filter_axis_EnableAutoRestart(&Xlap_fil_axis);
// axis_switch_0, 2to1, Select S01_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR+0x40), 0x1);
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR), 0x2); // Commit registers
return(0);
}
// cam_return.c
// 2015/06/25 by marsee
//
#include <stdio.h>
#include "xlap_filter_axis.h"
#include "xparameters.h"
int main(){
XLap_filter_axis Xlap_fil_axis;
XLap_filter_axis_Config *Xlap_fil_axisPtr;
// Look Up the device configuration
Xlap_fil_axisPtr = XLap_filter_axis_LookupConfig(0);
if (!Xlap_fil_axisPtr){
fprintf(stderr, "XLap_filter_axis configuration failed.\n");
return(-1);
}
// Initialize the Device
int Xlap_status = XLap_filter_axis_CfgInitialize(&Xlap_fil_axis, Xlap_fil_axisPtr);
if (Xlap_status != XST_SUCCESS){
fprintf(stderr, "Could not Initialize XLap_filter_axis\n");
return(-1);
}
// 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
// laplacian filter AXIS AutoRestart disable
XLap_filter_axis_DisableAutoRestart(&Xlap_fil_axis);
// 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
return(0);
}
// cam_disp_axis.c
// 2015/06/14 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 "xaxivdma.h"
#include "xil_io.h"
#include "xparameters.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
static XAxiVdma_DmaSetup Vdma0_WriteCfg;
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(){
// malloc frame buffer
// unsigned int *frame_buffer = (unsigned int *)malloc(HORIZONTAL_PIXELS * VERTICAL_LINES * PIXEL_NUM_OF_BYTES * NUMBER_OF_WRITE_FRAMES);
// AXI VDMA Initialization sequence
XAxiVdma_Config *XAxiVdma0_Config;
XAxiVdma XAxiVdma0;
int XAxiVdma0_Status;
XAxiVdma0_Config = XAxiVdma_LookupConfig(XPAR_CAMERA_INTERFACE_AXI_VDMA_0_DEVICE_ID); // Look up the hardware configuration for a device instance
if (XAxiVdma0_Config == NULL){
fprintf(stderr, "No AXI VDMA found\n");
return(-1);
}
XAxiVdma0_Status = XAxiVdma_CfgInitialize(&XAxiVdma0, XAxiVdma0_Config, XAxiVdma0_Config->BaseAddress); // Initialize the driver with hardware configuration
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_CfgInitialize() failed\n");
return(-1);
}
XAxiVdma_Reset(&XAxiVdma0, XAXIVDMA_WRITE);
while(XAxiVdma_ResetNotDone(&XAxiVdma0, XAXIVDMA_WRITE)) ;
XAxiVdma0_Status = XAxiVdma_SetFrmStore(&XAxiVdma0, NUMBER_OF_WRITE_FRAMES, XAXIVDMA_WRITE); // Set the number of frame store buffers to use.
Vdma0_WriteCfg.VertSizeInput = VERTICAL_LINES;
Vdma0_WriteCfg.HoriSizeInput = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES;
Vdma0_WriteCfg.Stride = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES; // Indicates the number of address bytes between the first pixels of each video line.
Vdma0_WriteCfg.FrameDelay = 0; // Indicates the minimum number of frame buffers the Genlock slave is to be behind the locked master. This field is only used if the channel is enabled for Genlock Slave operations. This field has no meaning in other Genlock modes.
Vdma0_WriteCfg.EnableCircularBuf = 1; // Indicates frame buffer Circular mode or frame buffer Park mode. 1 = Circular Mode Engine continuously circles through frame buffers.
Vdma0_WriteCfg.EnableSync = 0; // Enables Genlock or Dynamic Genlock Synchronization. 0 = Genlock or Dynamic Genlock Synchronization disabled.
Vdma0_WriteCfg.PointNum = 0; // No Gen-Lock
Vdma0_WriteCfg.EnableFrameCounter = 0; // Endless transfers
Vdma0_WriteCfg.FixedFrameStoreAddr = 0; // We are not doing parking
XAxiVdma0_Status = XAxiVdma_DmaConfig(&XAxiVdma0, XAXIVDMA_WRITE, &Vdma0_WriteCfg);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaConfig() failed\n");
return(-1);
}
// Frame buffer address set
unsigned int frame_addr = (unsigned int)FRAME_BUFFER_ADDRESS;
int i;
for (i=0; i<NUMBER_OF_WRITE_FRAMES; i++){
Vdma0_WriteCfg.FrameStoreStartAddr[i] = frame_addr;
frame_addr += HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES * VERTICAL_LINES;
}
XAxiVdma0_Status = XAxiVdma_DmaSetBufferAddr(&XAxiVdma0, XAXIVDMA_WRITE, Vdma0_WriteCfg.FrameStoreStartAddr);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaSetBufferAddr() failed\n");
return(-1);
}
// 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
// VDMA start
XAxiVdma0_Status = XAxiVdma_DmaStart(&XAxiVdma0, XAXIVDMA_WRITE);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaStart() failed\n");
return(-1);
}
// mt9d111_inf_axis_0, axi_iic_0, bitmap_disp_cntrler_axi_master_0
volatile unsigned int *bmdc_axi_lites;
volatile unsigned int *mt9d111_axi_lites;
volatile unsigned int *mt9d111_i2c_axi_lites;
bmdc_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_0_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;
bmdc_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller 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_axis.c
// 2015/06/14 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 "xaxivdma.h"
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"
#define NUMBER_OF_WRITE_FRAMES 1
#define HORIZONTAL_PIXELS 800
#define VERTICAL_LINES 600
#define PIXEL_NUM_OF_BYTES 4
static XAxiVdma_DmaSetup Vdma0_WriteCfg;
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(){
// malloc frame buffer
unsigned int *frame_buffer = (unsigned int *)malloc(HORIZONTAL_PIXELS * VERTICAL_LINES * PIXEL_NUM_OF_BYTES * NUMBER_OF_WRITE_FRAMES);
// AXI VDMA Initialization sequence
XAxiVdma_Config *XAxiVdma0_Config;
XAxiVdma XAxiVdma0;
int XAxiVdma0_Status;
XAxiVdma0_Config = XAxiVdma_LookupConfig(XPAR_CAMERA_INTERFACE_AXI_VDMA_0_DEVICE_ID); // Look up the hardware configuration for a device instance
if (XAxiVdma0_Config == NULL){
fprintf(stderr, "No AXI VDMA found\n");
return(-1);
}
XAxiVdma0_Status = XAxiVdma_CfgInitialize(&XAxiVdma0, XAxiVdma0_Config, XAxiVdma0_Config->BaseAddress); // Initialize the driver with hardware configuration
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_CfgInitialize() failed\n");
return(-1);
}
XAxiVdma_Reset(&XAxiVdma0, XAXIVDMA_WRITE);
while(XAxiVdma_ResetNotDone(&XAxiVdma0, XAXIVDMA_WRITE)) ;
XAxiVdma0_Status = XAxiVdma_SetFrmStore(&XAxiVdma0, NUMBER_OF_WRITE_FRAMES, XAXIVDMA_WRITE); // Set the number of frame store buffers to use.
Vdma0_WriteCfg.VertSizeInput = VERTICAL_LINES;
Vdma0_WriteCfg.HoriSizeInput = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES;
Vdma0_WriteCfg.Stride = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES; // Indicates the number of address bytes between the first pixels of each video line.
Vdma0_WriteCfg.FrameDelay = 0; // Indicates the minimum number of frame buffers the Genlock slave is to be behind the locked master. This field is only used if the channel is enabled for Genlock Slave operations. This field has no meaning in other Genlock modes.
Vdma0_WriteCfg.EnableCircularBuf = 1; // Indicates frame buffer Circular mode or frame buffer Park mode. 1 = Circular Mode Engine continuously circles through frame buffers.
Vdma0_WriteCfg.EnableSync = 0; // Enables Genlock or Dynamic Genlock Synchronization. 0 = Genlock or Dynamic Genlock Synchronization disabled.
Vdma0_WriteCfg.PointNum = 0; // No Gen-Lock
Vdma0_WriteCfg.EnableFrameCounter = 0; // Endless transfers
Vdma0_WriteCfg.FixedFrameStoreAddr = 0; // We are not doing parking
XAxiVdma0_Status = XAxiVdma_DmaConfig(&XAxiVdma0, XAXIVDMA_WRITE, &Vdma0_WriteCfg);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaConfig() failed\n");
return(-1);
}
// Frame buffer address set
unsigned int frame_addr = (unsigned int)frame_buffer;
int i;
for (i=0; i<NUMBER_OF_WRITE_FRAMES; i++){
Vdma0_WriteCfg.FrameStoreStartAddr[i] = frame_addr;
frame_addr += HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES * VERTICAL_LINES;
}
XAxiVdma0_Status = XAxiVdma_DmaSetBufferAddr(&XAxiVdma0, XAXIVDMA_WRITE, Vdma0_WriteCfg.FrameStoreStartAddr);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaSetBufferAddr() failed\n");
return(-1);
}
// 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
// VDMA start
XAxiVdma0_Status = XAxiVdma_DmaStart(&XAxiVdma0, XAXIVDMA_WRITE);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaStart() failed\n");
return(-1);
}
// mt9d111_inf_axis_0, axi_iic_0, bitmap_disp_cntrler_axi_master_0
volatile unsigned int *bmdc_axi_lites;
volatile unsigned int *mt9d111_axi_lites;
volatile unsigned int *mt9d111_i2c_axi_lites;
bmdc_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_0_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;
bmdc_axi_lites[0] = (volatile unsigned int)frame_buffer; // Bitmap Display Controller start
mt9d111_axi_lites[0] = (volatile unsigned int)frame_buffer; // 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
// VDMA start
/* XAxiVdma0_Status = XAxiVdma_DmaStart(&XAxiVdma0, XAXIVDMA_WRITE); if (XAxiVdma0_Status != XST_SUCCESS){ fprintf(stderr, "XAxiVdma_DmaStart() failed\n"); return(-1); } */
return(0);
}
// cam_disp_axis.c
// 2015/06/14 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 "xaxivdma.h"
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"
#define NUMBER_OF_WRITE_FRAMES 1
#define HORIZONTAL_PIXELS 800
#define VERTICAL_LINES 600
#define PIXEL_NUM_OF_BYTES 4
static XAxiVdma_DmaSetup Vdma0_WriteCfg;
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(){
// malloc frame buffer
unsigned int *frame_buffer = (unsigned int *)malloc(HORIZONTAL_PIXELS * VERTICAL_LINES * PIXEL_NUM_OF_BYTES * NUMBER_OF_WRITE_FRAMES);
// AXI VDMA Initialization sequence
XAxiVdma_Config *XAxiVdma0_Config;
XAxiVdma XAxiVdma0;
int XAxiVdma0_Status;
XAxiVdma0_Config = XAxiVdma_LookupConfig(XPAR_CAMERA_INTERFACE_AXI_VDMA_0_DEVICE_ID); // Look up the hardware configuration for a device instance
if (XAxiVdma0_Config == NULL){
fprintf(stderr, "No AXI VDMA found\n");
return(-1);
}
XAxiVdma0_Status = XAxiVdma_CfgInitialize(&XAxiVdma0, XAxiVdma0_Config, XAxiVdma0_Config->BaseAddress); // Initialize the driver with hardware configuration
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_CfgInitialize() failed\n");
return(-1);
}
XAxiVdma_Reset(&XAxiVdma0, XAXIVDMA_WRITE);
while(XAxiVdma_ResetNotDone(&XAxiVdma0, XAXIVDMA_WRITE)) ;
XAxiVdma0_Status = XAxiVdma_SetFrmStore(&XAxiVdma0, NUMBER_OF_WRITE_FRAMES, XAXIVDMA_WRITE); // Set the number of frame store buffers to use.
Vdma0_WriteCfg.VertSizeInput = VERTICAL_LINES;
Vdma0_WriteCfg.HoriSizeInput = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES;
Vdma0_WriteCfg.Stride = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES; // Indicates the number of address bytes between the first pixels of each video line.
Vdma0_WriteCfg.FrameDelay = 0; // Indicates the minimum number of frame buffers the Genlock slave is to be behind the locked master. This field is only used if the channel is enabled for Genlock Slave operations. This field has no meaning in other Genlock modes.
Vdma0_WriteCfg.EnableCircularBuf = 1; // Indicates frame buffer Circular mode or frame buffer Park mode. 1 = Circular Mode Engine continuously circles through frame buffers.
Vdma0_WriteCfg.EnableSync = 0; // Enables Genlock or Dynamic Genlock Synchronization. 0 = Genlock or Dynamic Genlock Synchronization disabled.
Vdma0_WriteCfg.PointNum = 0; // No Gen-Lock
Vdma0_WriteCfg.EnableFrameCounter = 0; // Endless transfers
Vdma0_WriteCfg.FixedFrameStoreAddr = 0; // We are not doing parking
XAxiVdma0_Status = XAxiVdma_DmaConfig(&XAxiVdma0, XAXIVDMA_WRITE, &Vdma0_WriteCfg);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaConfig() failed\n");
return(-1);
}
// Frame buffer address set
unsigned int frame_addr = (unsigned int)frame_buffer;
int i;
for (i=0; i<NUMBER_OF_WRITE_FRAMES; i++){
Vdma0_WriteCfg.FrameStoreStartAddr[i] = frame_addr;
frame_addr += HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES * VERTICAL_LINES;
}
XAxiVdma0_Status = XAxiVdma_DmaSetBufferAddr(&XAxiVdma0, XAXIVDMA_WRITE, Vdma0_WriteCfg.FrameStoreStartAddr);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaSetBufferAddr() failed\n");
return(-1);
}
// 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
// mt9d111_inf_axis_0, axi_iic_0, bitmap_disp_cntrler_axi_master_0
volatile unsigned int *bmdc_axi_lites;
volatile unsigned int *mt9d111_axi_lites;
volatile unsigned int *mt9d111_i2c_axi_lites;
bmdc_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_0_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;
bmdc_axi_lites[0] = (volatile unsigned int)frame_buffer; // Bitmap Display Controller start
mt9d111_axi_lites[0] = (volatile unsigned int)frame_buffer; // 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
// VDMA start
XAxiVdma0_Status = XAxiVdma_DmaStart(&XAxiVdma0, XAXIVDMA_WRITE);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaStart() failed\n");
return(-1);
}
return(0);
}
Importing IP drivers in SDK
Vivado Design Suite Tutorial: High-Level Synthesis UG871 (v 2013.2) June 19, 2013 232ページ ”Step 6: Developing Software and Running it on the ZYNQ System”
sdk 13.2 add custom ip driver
AR# 35443 12.1 EDK - SDK でローカル プロジェクト ディレクトリにあるソフトウェア ドライバー アップデートが検出できない
にすれば良さそうだ。カメラの画像を表示する時は
0x40 を 0x0
0x44 を 0x80000000
0x0 を 0x2
ラプラシアンフィルタIP を通す場合は
0x40 を 0x80000000
0x44 を 0x0
0x0 を 0x2
// display_cont.cpp
// 2015/06/03 by marsee
//
// 画面を4分割した第1象限は赤、第2象限は緑、第3象限は青、第4象限は白を表示する
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
// SVGA 解像度
#define H_ACTIVE_VIDEO 800
#define H_FRONT_PORCH 40
#define H_SYNC_PULSE 128
#define H_BACK_PORCH 88
#define H_SUM (H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH)
#define V_ACTIVE_VIDEO 600
#define V_FRONT_PORCH 1
#define V_SYNC_PULSE 4
#define V_BACK_PORCH 23
#define V_SUM (V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH)
void display_cont_sub(ap_uint<8> *red, ap_uint<8> *green, ap_uint<8> *blue, ap_uint<1> *display_enable, ap_uint<1> *hsyncx, ap_uint<1> *vsyncx){
#pragma HLS INTERFACE ap_none register port=red
#pragma HLS INTERFACE ap_none register port=green
#pragma HLS INTERFACE ap_none register port=blue
#pragma HLS INTERFACE ap_none register port=display_enable
#pragma HLS INTERFACE ap_none register port=hsyncx
#pragma HLS INTERFACE ap_none register port=vsyncx
#pragma HLS INTERFACE ap_ctrl_none port=return
ap_uint<16> h_count, v_count;
for (v_count=0; v_count<V_SUM; v_count++){
for (h_count=0; h_count<H_SUM; h_count++){
#pragma HLS PIPELINE rewind
if (h_count > (H_ACTIVE_VIDEO +H_FRONT_PORCH) && h_count < (H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE))
*hsyncx = 0;
else
*hsyncx = 1;
if (v_count > (V_ACTIVE_VIDEO + V_FRONT_PORCH) && v_count < (V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE))
*vsyncx = 0;
else
*vsyncx = 1;
if (h_count < H_ACTIVE_VIDEO && v_count < V_ACTIVE_VIDEO)
*display_enable = 1;
else
*display_enable = 0;
if (v_count < V_ACTIVE_VIDEO/2){
if (h_count < H_ACTIVE_VIDEO/2){
*red=0xff; *green=0; *blue=0;
} else if (h_count < H_ACTIVE_VIDEO){
*red=0; *green=0xff; *blue=0;
} else {
*red=0; *green=0; *blue=0;
}
} else if (v_count < V_ACTIVE_VIDEO){
if (h_count < H_ACTIVE_VIDEO/2){
*red=0; *green=0; *blue=0xff;
} else if (h_count < H_ACTIVE_VIDEO){
*red=0xff; *green=0xff; *blue=0xff;
} else {
*red=0; *green=0; *blue=0;
}
} else {
*red=0; *green=0; *blue=0;
}
}
}
}
//
// disp_cont_top.v
// 15/06/07 by marsee
//
`default_nettype none
module disp_cont_top (
input wire clk,
input wire reset,
output wire [4:0] vga_red,
output wire [5:0] vga_green,
output wire [4:0] vga_blue,
output wire vga_hsync,
output wire vga_vsync
);
wire [7:0] red;
wire [7:0] green;
wire [7:0] blue;
display_cont_sub display_cont_i (
.ap_clk(clk),
.ap_rst(reset),
.red_V(red),
.green_V(green),
.blue_V(blue),
.display_enable_V(),
.hsyncx_V(vga_hsync),
.vsyncx_V(vga_vsync)
);
assign vga_red = red[7:3];
assign vga_green = green[7:2];
assign vga_blue = blue[7:3];
endmodule
`default_nettype wire
set_property PACKAGE_PIN L16 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
create_clock -add -name sys_clk_pin -period 8.00 -waveform {0 4} [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[0]}]
set_property PACKAGE_PIN J18 [get_ports {vga_blue[3]}]
set_property PACKAGE_PIN K19 [get_ports {vga_blue[2]}]
set_property PACKAGE_PIN M20 [get_ports {vga_blue[1]}]
set_property PACKAGE_PIN P20 [get_ports {vga_blue[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[4]}]
set_property PACKAGE_PIN G19 [get_ports {vga_blue[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[0]}]
set_property PACKAGE_PIN F20 [get_ports {vga_green[5]}]
set_property PACKAGE_PIN H20 [get_ports {vga_green[4]}]
set_property PACKAGE_PIN J19 [get_ports {vga_green[3]}]
set_property PACKAGE_PIN L19 [get_ports {vga_green[2]}]
set_property PACKAGE_PIN N20 [get_ports {vga_green[1]}]
set_property PACKAGE_PIN H18 [get_ports {vga_green[0]}]
set_property PACKAGE_PIN F19 [get_ports {vga_red[4]}]
set_property PACKAGE_PIN G20 [get_ports {vga_red[3]}]
set_property PACKAGE_PIN J20 [get_ports {vga_red[2]}]
set_property PACKAGE_PIN L20 [get_ports {vga_red[1]}]
set_property PACKAGE_PIN M19 [get_ports {vga_red[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports vga_hsync]
set_property IOSTANDARD LVCMOS33 [get_ports vga_vsync]
set_property PACKAGE_PIN P19 [get_ports vga_hsync]
set_property PACKAGE_PIN R19 [get_ports vga_vsync]
# btn[0]
set_property PACKAGE_PIN R18 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
//#pragma HLS INTERFACE ap_ctrl_hs port=return
#pragma HLS INTERFACE ap_ctrl_none port=return
`default_nettype none
`timescale 100ps / 1ps
// display_cont_tb.v
// by marsee
// 2015/06/05
//
module display_cont_tb;
wire ap_clk;
wire ap_rst;
wire [7:0] red_V;
wire [7:0] green_V;
wire [7:0] blue_V;
wire display_enable_V;
wire hsyncx_V;
wire vsyncx_V;
//display_cont_sub uut (
display_cont uut (
.ap_clk(ap_clk),
.ap_rst(ap_rst),
.red_V(red_V),
.green_V(green_V),
.blue_V(blue_V),
.display_enable_V(display_enable_V),
.hsyncx_V(hsyncx_V),
.vsyncx_V(vsyncx_V)
);
// clk_gen のインスタンス(ap_clk)
clk_gen #(
.CLK_PERIOD(250), // 25 nsec, 40 MHz
.CLK_DUTY_CYCLE(0.5),
.CLK_OFFSET(0),
.START_STATE(1'b0)
) ACLKi (
.clk_out(ap_clk)
);
// reset_gen のインスタンス
reset_gen #(
.RESET_STATE(1'b1),
.RESET_TIME(1000) // 100nsec
) RESETi (
.reset_out(ap_rst),
.init_done()
);
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,
output reg init_done
);
begin
initial begin
reset_out = RESET_STATE;
init_done = 1'b0;
#RESET_TIME;
reset_out = ~RESET_STATE;
init_done = 1'b1;
end
end
endmodule
`default_nettype wire
// display_cont.cpp
// 2015/06/03 by marsee
//
// 画面を4分割した第1象限は赤、第2象限は緑、第3象限は青、第4象限は白を表示する
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
// SVGA 解像度
#define H_ACTIVE_VIDEO 800
#define H_FRONT_PORCH 40
#define H_SYNC_PULSE 128
#define H_BACK_PORCH 88
#define H_SUM (H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH)
#define V_ACTIVE_VIDEO 600
#define V_FRONT_PORCH 1
#define V_SYNC_PULSE 4
#define V_BACK_PORCH 23
#define V_SUM (V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH)
void display_cont(ap_uint<8> *red, ap_uint<8> *green, ap_uint<8> *blue, ap_uint<1> *display_enable, ap_uint<1> *hsyncx, ap_uint<1> *vsyncx){
#pragma HLS INTERFACE ap_none register port=red
#pragma HLS INTERFACE ap_none register port=green
#pragma HLS INTERFACE ap_none register port=blue
#pragma HLS INTERFACE ap_none register port=display_enable
#pragma HLS INTERFACE ap_none register port=hsyncx
#pragma HLS INTERFACE ap_none register port=vsyncx
#pragma HLS INTERFACE ap_ctrl_none port=return
ap_uint<16> h_count, v_count;
while(1){
for (v_count=0; v_count<V_SUM; v_count++){
for (h_count=0; h_count<H_SUM; h_count++){
#pragma HLS PIPELINE
#pragma HLS LATENCY min=1 max=1
if (h_count > (H_ACTIVE_VIDEO +H_FRONT_PORCH) && h_count < (H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE))
*hsyncx = 0;
else
*hsyncx = 1;
if (v_count > (V_ACTIVE_VIDEO + V_FRONT_PORCH) && v_count < (V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE))
*vsyncx = 0;
else
*vsyncx = 1;
if (h_count < H_ACTIVE_VIDEO && v_count < V_ACTIVE_VIDEO)
*display_enable = 1;
else
*display_enable = 0;
if (v_count < V_ACTIVE_VIDEO/2){
if (h_count < H_ACTIVE_VIDEO/2){
*red=0xff; *green=0; *blue=0;
} else if (h_count < H_ACTIVE_VIDEO){
*red=0; *green=0xff; *blue=0;
} else {
*red=0; *green=0; *blue=0;
}
} else if (v_count < V_ACTIVE_VIDEO){
if (h_count < H_ACTIVE_VIDEO/2){
*red=0; *green=0; *blue=0xff;
} else if (h_count < H_ACTIVE_VIDEO){
*red=0xff; *green=0xff; *blue=0xff;
} else {
*red=0; *green=0; *blue=0;
}
} else {
*red=0; *green=0; *blue=0;
}
}
}
}
}
void display_cont_sub(ap_uint<8> *red, ap_uint<8> *green, ap_uint<8> *blue, ap_uint<1> *display_enable, ap_uint<1> *hsyncx, ap_uint<1> *vsyncx){
#pragma HLS INTERFACE ap_none register port=red
#pragma HLS INTERFACE ap_none register port=green
#pragma HLS INTERFACE ap_none register port=blue
#pragma HLS INTERFACE ap_none register port=display_enable
#pragma HLS INTERFACE ap_none register port=hsyncx
#pragma HLS INTERFACE ap_none register port=vsyncx
#pragma HLS INTERFACE ap_ctrl_hs port=return
ap_uint<16> h_count, v_count;
for (v_count=0; v_count<V_SUM; v_count++){
for (h_count=0; h_count<H_SUM; h_count++){
#pragma HLS PIPELINE
#pragma HLS LATENCY min=1 max=1
if (h_count > (H_ACTIVE_VIDEO +H_FRONT_PORCH) && h_count < (H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE))
*hsyncx = 0;
else
*hsyncx = 1;
if (v_count > (V_ACTIVE_VIDEO + V_FRONT_PORCH) && v_count < (V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE))
*vsyncx = 0;
else
*vsyncx = 1;
if (h_count < H_ACTIVE_VIDEO && v_count < V_ACTIVE_VIDEO)
*display_enable = 1;
else
*display_enable = 0;
if (v_count < V_ACTIVE_VIDEO/2){
if (h_count < H_ACTIVE_VIDEO/2){
*red=0xff; *green=0; *blue=0;
} else if (h_count < H_ACTIVE_VIDEO){
*red=0; *green=0xff; *blue=0;
} else {
*red=0; *green=0; *blue=0;
}
} else if (v_count < V_ACTIVE_VIDEO){
if (h_count < H_ACTIVE_VIDEO/2){
*red=0; *green=0; *blue=0xff;
} else if (h_count < H_ACTIVE_VIDEO){
*red=0xff; *green=0xff; *blue=0xff;
} else {
*red=0; *green=0; *blue=0;
}
} else {
*red=0; *green=0; *blue=0;
}
}
}
}
cd C:/Users/Masaaki/Documents/Vivado_HLS/ZYBO/display_cont/solution1/sim/verilog
current_fileset
open_wave_database display_cont_sub.wdb
open_wave_config display_cont_sub.wcfg
//
// display_cont_tb.cpp
// 2015/06/03 by marsee
//
#include <stdio.h>
#include <string.h>
#include <ap_int.h>
void display_cont_sub(ap_uint<8> *red, ap_uint<8> *green, ap_uint<8> *blue, ap_uint<1> *display_enable, ap_uint<1> *hsyncx, ap_uint<1> *vsyncx);
int main(){
ap_uint<8> redb, *red;
ap_uint<8> greenb, *green;
ap_uint<8> blueb, *blue;
ap_uint<1> deb, *display_enable;
ap_uint<1> hb, *hsyncx;
ap_uint<1> vb, *vsyncx;
red = &redb;
green = &greenb;
blue = &blueb;
display_enable = &deb;
hsyncx = &hb;
vsyncx = &vb;
display_cont_sub(red, green, blue, display_enable, hsyncx, vsyncx);
return 0;
}
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
- | 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 | - | - | - | - |