#include "xaxivdma.h" #include "xaxivdma_i.h" #include "xhls_sobel.h" #include "sleep.h"
#include"xparameters.h"
#define DISPLAY_VDMA XPAR_AXI_VDMA_0_BASEADDR + 0 //VDMA0在DDR中的映射
#define SOBEL_VDMA XPAR_AXI_VDMA_1_BASEADDR + 0 //VDMA1在DDR中的映射 #define DIS_X 1280 //显示区域的行、场信号,设置显示屏的大小 #define DIS_Y 720 #define SOBEL_ROW 512 //图片显示区域的大小 #define SOBEL_COL 512 #define SOBEL_S2MM 0x08000000 //sobel处理ip的接收数据的存储地址 #define SOBEL_MM2S 0x0A000000 //sobel处理ip的处理完毕之后发送数据的存储地址 #define DISPLAY_MM2S 0x0C000000 //仅可读取的VDVA的数据发送地址 u32 *BufferPtr[3]; //定义一个32位无符号的缓存指针 static XHls_sobel sobel; //定义一个sobel结构体 //函数声明,该函数用于将数据刷入DDR void Xil_DCacheFlush(void); // 所有数据格式 为 AGBR,低位的透明度暂不起作用 extern const unsigned char gImage_lena[1048584];
/*
下面函数的作用是对控制sobel的数据来源与去向的VDMA进行操作配置,其流程为
1、将VDMA控制器复位,延时,然后进行锁定
2、设置数据到DDR三帧缓存的地址0,4,8
3、设置显示图片的的行宽度,datasheet中说该信号indicate the horizontal size in bytes,一个像素点为4bytes
4、设置显示图片的的高,indicate verical size in lines of the data to transfer
然后同理设置从VDMA发送数据到SOBEL进行处理的图像数据帧缓存
*/ void SOBEL_VDMA_setting(unsigned int width,unsigned int height,unsigned int s2mm_addr,unsigned int mm2s_addr) { //S2MM Xil_Out32(SOBEL_VDMA + 0x30, 0x4); //reset S2MM VDMA Control Register usleep(10); Xil_Out32(SOBEL_VDMA + 0x30, 0x0); //genlock Xil_Out32(SOBEL_VDMA + 0xAC, s2mm_addr);//S2MM Start Addresses Xil_Out32(SOBEL_VDMA + 0xAC+4, s2mm_addr); Xil_Out32(SOBEL_VDMA + 0xAC+8, s2mm_addr); Xil_Out32(SOBEL_VDMA + 0xA4, width*4);//S2MM Horizontal Size Xil_Out32(SOBEL_VDMA + 0xA0, height);//S2MM Vertical Size start an S2M Xil_Out32(SOBEL_VDMA + 0xA8, width*4);//S2MM Frame Delay and Stride Xil_Out32(SOBEL_VDMA + 0x30, 0x3);//S2MM VDMA Control Register // Xil_DCacheFlush(); //MM2S Xil_Out32(SOBEL_VDMA + 0x00,0x00000003); // enable circular mode Xil_Out32(SOBEL_VDMA + 0x5c,mm2s_addr); // start address Xil_Out32(SOBEL_VDMA + 0x60,mm2s_addr); // start address Xil_Out32(SOBEL_VDMA + 0x64,mm2s_addr); // start address Xil_Out32(SOBEL_VDMA + 0x58,(width*4)); // h offset Xil_Out32(SOBEL_VDMA + 0x54,(width*4)); // h size Xil_Out32(SOBEL_VDMA + 0x50,height); // v size //Xil_DCacheFlush(); } /*
本函数仅用于将数据发送到视频数据流处理模块,流程为:
1、设置成循环显示模式,然后设置三帧数据缓存的起始地址
*/ void DISPLAY_VDMA_setting(unsigned int width,unsigned height,unsigned int mm2s_addr) { Xil_Out32((DISPLAY_VDMA + 0x000), 0x00000003); // enable circular mode Xil_Out32((DISPLAY_VDMA + 0x05c), mm2s_addr); // start address Xil_Out32((DISPLAY_VDMA + 0x060), mm2s_addr); // start address Xil_Out32((DISPLAY_VDMA + 0x064), mm2s_addr); // start address Xil_Out32((DISPLAY_VDMA + 0x058), (width*4)); // h offset (640 * 4) bytes Xil_Out32((DISPLAY_VDMA + 0x054), (width*4)); // h size (640 * 4) bytes Xil_Out32((DISPLAY_VDMA + 0x050), height); // v size (480) } /*
sobel数据输入处理部分,ADDr是MM2S即数据从DDR到VDMA的数据通道,将数据写入对应位置后,将数据刷入DDR,
刷入的位置是将将数据发送到MM2S的起始位置
*/ void SOBEL_DDRWR(unsigned int addr,unsigned int cols,unsigned int rows) { u32 i=0; u32 j=0; u32 r,g,b; for(i=0;i<cols;i++) { for(j=0;j<rows;j++) { b= gImage_lena[(j+i*cols)*4+1]; //B-G-R g= gImage_lena[(j+i*cols)*4+2]; r= gImage_lena[(j+i*cols)*4+3]; Xil_Out32((addr+(j+i*cols)*4),((r<<24)|(g<<16)|(b<<8)|0x0)); } } Xil_DCacheFlush(); }
/*
sobel IP核的设置
1、设置处理图片的宽和高,然后禁止自启动模式,禁用中断,
2、设置数据配套VDMA,然后将数据输入DDR
3、启动Sobel ip核
*/ void SOBEL_Setup() { //const int cols = 512; //const int rows = 512; XHls_sobel_SetRows(&sobel, SOBEL_COL); XHls_sobel_SetCols(&sobel, SOBEL_ROW); XHls_sobel_DisableAutoRestart(&sobel); XHls_sobel_InterruptGlobalDisable(&sobel); SOBEL_VDMA_setting(SOBEL_ROW,SOBEL_COL,SOBEL_S2MM,SOBEL_MM2S); SOBEL_DDRWR(SOBEL_MM2S,SOBEL_ROW,SOBEL_COL); //init_hls_sobel_dma(cols,rows, VIDEO_BASEADDR, HLS_VDMA_MM2S_ADDR); //DDRVideoWr(HLS_VDMA_MM2S_ADDR, cols,rows); XHls_sobel_Start(&sobel); }
//设置显示屏背景色为全黑RGB=000 void Set_blackground(u32 size_x,u32 size_y,u32 disp_addr) { u32 i=0; u32 j=0; //u32 r,g,b; for(j=0;j<size_y;j++) { for(i=0;i<size_x;i++) { Xil_Out32((disp_addr+(i+j*size_x)*4),0); //black } } Xil_DCacheFlush(); } /*
图片显示,
显示两张,一张是原始图片,另一张是出力轴的图片,两张根据type进行区别,将显示数据从addr中读出,然后将数据写入到显示区域,最后将数据刷入DDR
*/ void show_img(u32 x, u32 y, u32 disp_base_addr, const unsigned char * addr, u32 size_x, u32 size_y,u32 type) { //计算图片 左上角坐标 u32 i=0; u32 j=0; u32 r,g,b; u32 start_addr=disp_base_addr; start_addr = disp_base_addr + 4*x + y*4*DIS_X; for(j=0;j<size_y;j++) { for(i=0;i<size_x;i++) { if(type==0) { b = *(addr+(i+j*size_x)*4+2); //08 g = *(addr+(i+j*size_x)*4+1); //60 r = *(addr+(i+j*size_x)*4); //01 } else { b = *(addr+(i+j*size_x)*4+1); //08 g = *(addr+(i+j*size_x)*4+2); //60 r = *(addr+(i+j*size_x)*4+3); //01 } Xil_Out32((start_addr+(i+j*DIS_X)*4),((r<<16)|(g<<8)|(b<<0)|0x0)); } } Xil_DCacheFlush(); } int main(void) { //Xil_DCacheFlush(); xil_printf("Starting the first VDMA "); int status = XHls_sobel_Initialize(&sobel, XPAR_HLS_SOBEL_0_S_AXI_CONTROL_BUS_BASEADDR); if(0 != status) { xil_printf("XHls_Sobel_Initialize failed "); } SOBEL_Setup(); DISPLAY_VDMA_setting(DIS_X,DIS_Y,DISPLAY_MM2S); Set_blackground(1280,720,DISPLAY_MM2S); /****************************** for(i=0;i<614400;i++) { Xil_Out32(VIDEO_BASEADDR0+i,0); } *******************************/ while(1) { //show_img(0,0,VIDEO_BASEADDR0,&gImage_beauty[0],563,600); //sleep(5); //show_img(0,0,VIDEO_BASEADDR0,&gImage_miz702_rgba[0],375,400); //sleep(5); show_img(0,0,DISPLAY_MM2S,(void*)SOBEL_S2MM,512,512,0); show_img(522,0,DISPLAY_MM2S,(void*)SOBEL_MM2S,512,512,1); } return 0; }
首先包含几个头文件,#include “xaxivdma.h”用于服务可读写操作的VDMA1,#include “xaxivdma_i.h”用于服务仅可读取的VDMA0,sleep.h用于延时服务,#include”xparameters.h”用于包含硬件IP的各种映射信息
最新评论