Sobel硬件实现的硬件代码分析(三)
阅读原文时间:2023年07月16日阅读:1

#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[]; //定义一个32位无符号的缓存指针
static XHls_sobel sobel; //定义一个sobel结构体

//函数声明,该函数用于将数据刷入DDR
void Xil_DCacheFlush(void);
// 所有数据格式 为 AGBR,低位的透明度暂不起作用
extern const unsigned char gImage_lena[];

/*
下面函数的作用是对控制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();
Xil_Out32(SOBEL_VDMA + 0x30, 0x0); //genlock
Xil_Out32(SOBEL_VDMA + 0xAC, s2mm_addr);//S2MM Start Addresses
Xil_Out32(SOBEL_VDMA + 0xAC+, s2mm_addr);
Xil_Out32(SOBEL_VDMA + 0xAC+, s2mm_addr);
Xil_Out32(SOBEL_VDMA + 0xA4, width*);//S2MM Horizontal Size
Xil_Out32(SOBEL_VDMA + 0xA0, height);//S2MM Vertical Size start an S2M
Xil_Out32(SOBEL_VDMA + 0xA8, width*);//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\*)); // h offset  
    Xil\_Out32(SOBEL\_VDMA + 0x54,(width\*)); // 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*)); // h offset (640 * 4) bytes
Xil_Out32((DISPLAY_VDMA + 0x054), (width*)); // 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=;
u32 j=;
u32 r,g,b;
for(i=;i<cols;i++)
{
for(j=;j<rows;j++)
{
b= gImage_lena[(j+i*cols)*+]; //B-G-R
g= gImage_lena[(j+i*cols)*+];
r= gImage_lena[(j+i*cols)*+];
Xil_Out32((addr+(j+i*cols)*),((r<<)|(g<<)|(b<<)|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=;
u32 j=;
//u32 r,g,b;
for(j=;j<size_y;j++)
{
for(i=;i<size_x;i++)
{
Xil_Out32((disp_addr+(i+j*size_x)*),); //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=;
u32 j=;
u32 r,g,b;
u32 start_addr=disp_base_addr;
start_addr = disp_base_addr + *x + y**DIS_X;
for(j=;j<size_y;j++)
{
for(i=;i<size_x;i++)
{
if(type==)
{
b = *(addr+(i+j*size_x)*+); //
g = *(addr+(i+j*size_x)*+); //
r = *(addr+(i+j*size_x)*); //
}
else
{
b = *(addr+(i+j*size_x)*+); //
g = *(addr+(i+j*size_x)*+); //
r = *(addr+(i+j*size_x)*+); //
}
Xil_Out32((start_addr+(i+j*DIS_X)*),((r<<)|(g<<)|(b<<)|0x0));
}
}
Xil_DCacheFlush();
}

int main(void)
{

//Xil\_DCacheFlush();  
xil\_printf("Starting the first VDMA \\n\\r");  
int status = XHls\_sobel\_Initialize(&sobel, XPAR\_HLS\_SOBEL\_0\_S\_AXI\_CONTROL\_BUS\_BASEADDR);  
if( != status)  
{  
    xil\_printf("XHls\_Sobel\_Initialize failed \\n");  
}  
SOBEL\_Setup();  
DISPLAY\_VDMA\_setting(DIS\_X,DIS\_Y,DISPLAY\_MM2S);  
Set\_blackground(,,DISPLAY\_MM2S);

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
for(i=0;i<614400;i++)  
{  
    Xil\_Out32(VIDEO\_BASEADDR0+i,0);  
}  
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/  
while()  
{  
    //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(,,DISPLAY\_MM2S,(void\*)SOBEL\_S2MM,,,);  
    show\_img(,,DISPLAY\_MM2S,(void\*)SOBEL\_MM2S,,,);  
}  
return ;  

}

首先包含几个头文件,#include "xaxivdma.h"用于服务可读写操作的VDMA1,#include "xaxivdma_i.h"用于服务仅可读取的VDMA0,sleep.h用于延时服务,#include"xparameters.h"用于包含硬件IP的各种映射信息

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章