本编文章在ADI官方HDMI例程的基础上进行修改,实现视频通路,为使用ZYNQ视频处理做好必要准备。
在 【ZYNQ-7000开发之九】使用VDMA在PL和PS之间传输视频流数据 这篇文章中,介绍了如何使用VDMA传输stream类型的视频流数据,本次实验将结合【ZYNQ-7000开发之三】ZYNQ平台的HDMI驱动测试这篇文章,本次实验默认大家已经完成了【ZYNQ-7000开发之三】和【ZYNQ-7000开发之九,至少要完成【ZYNQ-7000开发之三】,本次实验将在【ZYNQ-7000开发之三】的基础上直接修改。
本篇文章的思想是使用TPG产生stream类型的数据,然后用VDMA转换成Memory Map类型的数据写入到DDR3缓存,最后再用VDMA 从DDR3读出来转换成stream类型,发送给HDMI控制器,进而显示在HDMI显示器上。
TGP VDMA等的规范说明可以到官网下载最新版本
本文所使用的开发板是Miz702(兼容zedboard)
PC 开发环境版本:Vivado 2015.2 Xilinx SDK 2015.2
其它:HDMI显示器,串口线
/***************************************************************************//**
* @brief InitHdmiVideoPcore.
*******************************************************************************/
void InitHdmiVideoPcore(unsigned short horizontalActiveTime,
unsigned short horizontalBlankingTime,
unsigned short horizontalSyncOffset,
unsigned short horizontalSyncPulseWidth,
unsigned short verticalActiveTime,
unsigned short verticalBlankingTime,
unsigned short verticalSyncOffset,
unsigned short verticalSyncPulseWidth)
{
unsigned short horizontalCount = 0;
unsigned short verticalCount = 0;
unsigned short horizontalBackPorch = 0;
unsigned short verticalBackPorch = 0;
unsigned short horizontalDeMin = 0;
unsigned short horizontalDeMax = 0;
unsigned short verticalDeMin = 0;
unsigned short verticalDeMax = 0;
DDRVideoWr(horizontalActiveTime, verticalActiveTime);
horizontalCount = horizontalActiveTime +
horizontalBlankingTime;
verticalCount = verticalActiveTime +
verticalBlankingTime;
horizontalBackPorch = horizontalBlankingTime -
horizontalSyncOffset -
horizontalSyncPulseWidth;
verticalBackPorch = verticalBlankingTime -
verticalSyncOffset -
verticalSyncPulseWidth;
horizontalDeMin = horizontalSyncPulseWidth +
horizontalBackPorch;
horizontalDeMax = horizontalDeMin +
horizontalActiveTime;
verticalDeMin = verticalSyncPulseWidth +
verticalBackPorch;
verticalDeMax = verticalDeMin +
verticalActiveTime;
Xil_Out32((CFV_BASEADDR + AXI_HDMI_REG_HTIMING1),
((horizontalActiveTime << 16) | horizontalCount));
Xil_Out32((CFV_BASEADDR + AXI_HDMI_REG_HTIMING2),
horizontalSyncPulseWidth);
Xil_Out32((CFV_BASEADDR + AXI_HDMI_REG_HTIMING3),
((horizontalDeMax << 16) | horizontalDeMin));
Xil_Out32((CFV_BASEADDR + AXI_HDMI_REG_VTIMING1),
((verticalActiveTime << 16) | verticalCount));
Xil_Out32((CFV_BASEADDR + AXI_HDMI_REG_VTIMING2),
verticalSyncPulseWidth);
Xil_Out32((CFV_BASEADDR + AXI_HDMI_REG_VTIMING3),
((verticalDeMax << 16) | verticalDeMin));
Xil_Out32((CFV_BASEADDR + AXI_HDMI_REG_RESET), 0x1);
Xil_Out32((CFV_BASEADDR + AXI_HDMI_REG_SOURCE_SEL), 0x0);
Xil_Out32((CFV_BASEADDR + AXI_HDMI_REG_SOURCE_SEL), 0x1);
Xil_Out32(VDMA_BASEADDR + 0x30, 0x4); //reset S2MM VDMA Control Register
Xil_Out32(VDMA_BASEADDR + 0x30, 0x8); //genlock
Xil_Out32(VDMA_BASEADDR + 0xAC, 0x08000000);//S2MM Start Addresses
Xil_Out32(VDMA_BASEADDR + 0xAC+4, 0x0A000000);
Xil_Out32(VDMA_BASEADDR + 0xAC+8, 0x0D000000);
Xil_Out32(VDMA_BASEADDR + 0xA4, 640*4);//S2MM Horizontal Size
Xil_Out32(VDMA_BASEADDR + 0xA8, 640*4);//S2MM Frame Delay and Stride
Xil_Out32(VDMA_BASEADDR + 0x30, 0x3);//S2MM VDMA Control Register
Xil_Out32(VDMA_BASEADDR + 0xA0, 480);//S2MM Vertical Size start an S2M
Xil_DCacheFlush();
Xil_Out32((VDMA_BASEADDR + AXI_VDMA_REG_DMA_CTRL),
0x00000003); // enable circular mode
Xil_Out32((VDMA_BASEADDR + AXI_VDMA_REG_START_1),
0x08000000); // start address
Xil_Out32((VDMA_BASEADDR + AXI_VDMA_REG_START_2),
0x0A000000); // start address
Xil_Out32((VDMA_BASEADDR + AXI_VDMA_REG_START_3),
0x0D000000); // start address
Xil_Out32((VDMA_BASEADDR + AXI_VDMA_REG_FRMDLY_STRIDE),
(horizontalActiveTime*4)); // h offset
Xil_Out32((VDMA_BASEADDR + AXI_VDMA_REG_H_SIZE),
(horizontalActiveTime*4)); // h size
Xil_Out32((VDMA_BASEADDR + AXI_VDMA_REG_V_SIZE),
verticalActiveTime); // v size
}
目前通过zynq实现了640*480的视频显示,大家可以调试下其它的分辨率。此外,串口终端发送数据的时候会断开,不知道大家是否会遇到这个BUG。