DM6467的VPIF接口支持BT.1120和SMPTE 296M两种高清格式,其中BT.1120是1080P(1080I)分辨率,SMPTE296M是720P分辨率。我们这里直接测试BT.1120格式的高清视频。
我们开发板上的高清视频AD芯片是TVP7002,TVP7002支持的视频格式如图 1所示。可以看出,要测试BT.1120格式的视频输入,只能使用1080P50、1080P60、1080I60和1080I50,而1080P30不行。考虑到DM6467的处理能力,我们暂不测试1080P60,最终决定测试的视频格式为1080I60。
图 1 TVP7002支持的视频格式
1 BT.1120标准简介
BT.1120是世界电信联盟制定的一套高清视频格式规范,与BT.601类似。BT.1120标准定义了高清视频传输过程中的信号格式、接口规范等协议。对于BT.1120我们只需关注以下几点:
1, 每行1920个像素点,每帧1125行,其中1080有效行。
2, 图像频率包括60、50、30、25和24Hz,可以逐行、隔行和分段传输。
3, YCbCr传输时使用20bit,Cb和Cr复用;RGB传输时使用30bit。
4, 视频的帧同步采用SAV(Start ofActive Video)和EAV(End of Active Video)机制。
5, 在测试1080I60格式的视频时,亮度取样信号频率(像素点频率)为74.25MHz,如图 2所示。
6, 对于隔行扫描系统,BT.1120规定的场/段定时关系如图 3所示;针对1080I60格式的视频,具体的参数如图 4所示。
图 2 BT.1120采样频率表
图 3 隔行扫描中场/段定时关系
图 4 隔行扫描中场/段定时参数
在我们设计的电路中,TVP7002输出视频采用YCbCr编码,并且只传输高8位。TVP7002的时钟采用内部时钟,同时TVP7002也向VPIF提供参考时钟。另外,视频的同步信号时内嵌在RGB三个通道中的G通道,也即需要将G通道接到TVP7002的SOG(Sync on Green)引脚,电路原理图如图 5所示。
图 5 TVP7002输入信号电路原理图
2 CCS中调试TVP7002
高清视频信号进入DM6467的过程是:RCA高清插座->THS7353钳位放大器->TVP7002高清视频AD转换->SN74CBT16214DGGR总线切换->FPGA视频预处理->DM6467的VPIF视频接口,另外,DM6467通过CPLD管理整个系统的逻辑控制。
2.1 CPLD程序修改
CPLD主要负责输入视频的通道选择,选通标清输入或者高清输入。需要根据CPLD程序中的reg1各个bit的定义来设置正确的值。
------------------------------- Reg1 (0x3b) ----------------------------- -- [=0] [=1] -- BIT 0 TVP5147_RST *TVP5150 Normal TVP5150 Reset -- BIT 1 TVP5147_PWD *TVP5150 Normal Mode TVP5150 Power Down -- BIT 2 TVP7002_RST *TVP7002 Normal TVP7002 Reset -- BIT 3 TVP7002_PWD *TVP7002 Normal Mode TVP7002 Power Down -- BIT 4 TVP_SELECT *Select TVP5150 Select TVP7002 -- BIT 5 VID_IN_MODE *Standard Def In High Def In -- (CV/SV) (HD_Y/HD_C) -- BIT 6 VID_OUT_MODE *Standard Def Out High Def Out -- (ADV_S) (ADV_Y/ADV_C) -- BIT 7 - TVP5150/TVP7002 CMOS INPUT
|
其中最重要的bit4和bit5,bit4使能TVP7002或者TVP5150,bit5切换标清输入或者高清输入的数据信号,由于没有高清显示器,暂时bit6无意义。所以最终需要设置reg1的值为0x30。
另外,由于我们在开发板上添加了OV5642数字摄像头扩展板,所以需要略微修改逻辑控制,以兼容OV5642的程序。
-- Pin Control VID_INLO_S0 <= '0' when Enable_CV = '1' else '1'; -- CV VID_INLO_S1 <= '0' when Enable_CMOS_LO = '1' else '1'; -- HD_Y VID_INLO_S2 <= '1' ;
VID_INHI_S0 <= '1' ;--when Enable_SV = '1' else '0'; -- SV --VID_INHI_S1 <= '1' when Enable_HD_C = '1' else '0'; -- HD_C VID_INHI_S1 <= '0' when Enable_CMOS_HI = '1' else '1'; -- HD_C VID_INHI_S2 <= '1' ;
TVP5150_I2Cn <= '0' when Reg1(4) = '0' else '1'; TVP7002_I2Cn <= '0' when Reg1(4) = '1' else '1'; -- [U7] :TVP7002 |
2.2 FPGA程序修改
对于FPGA部分,暂时仍然是采用直连,不做任何视频预处理。在通过高清视频信号时,需特别注意TVP7002传过来的时钟信号,该信号频率比较高,为74.25MHz。要使Cyclone III FPGA输出与输入信号相同频率的时钟信号,需要使用锁相环,并将锁相环的默认时钟频率设置为大于等于74.25MHz。如果要处理1080P60格式的视频,则需要将锁相环的默认频率配置为148.5MHz。暂时我们只需要处理1080I60的视频,所以设置为74.25MHz就可以了,如图 6所示。
图 6 锁相环模块参数配置
2.3 VPIF寄存器参数配置
对于VPIF寄存器配置,重点是其中的通道控制寄存器(CH0_CTRL,CH1_CTRL)和与line format相关的各个寄存器。
VPIF的line format示意图如图 7所示。
图 7 VPIF的line format示意图
针对1080I60格式的视频,其中各个参数的值如图 8所示。
图 8 1080I60格式的各个参数
根据图 8,VPIF各寄存器的配置情况如下所示。
VPIF_CHCTRL0 = 0 // Capture Parameters | ( 0 << 12 ) // Input Field | ( 0 << 10 ) // Interlaced Format | ( 0 << 9 ) // No Vertical Ancillary | ( 0 << 8 ) // No Horizontal Ancillary | ( 1 << 6 ) // [2] Interrupt on Bottom Field | ( 0 << 4 ) // Raster | ( 0 << 3 ) // Y/C on seperate byte streams | ( 0 << 1 ) | ( 0 << 0 ); // Channel Disabled
channel0->regs->IMG_LINE_OFFSET = 1920; channel0->regs->HSIZE_CFG = ( 272 << 16 ) | ( 1920 << 0 ); channel0->regs->VSIZE_CFG0 = ( 1 << 16 ) | ( 21 << 0 ); channel0->regs->VSIZE_CFG1 = ( 561 << 16 ) | ( 564 << 0 ); channel0->regs->VSIZE_CFG2 = ( 584 << 16 ) | ( 1124 << 0 ); channel0->regs->VSIZE_CFG3 = ( 1125 );
VPIF_CHCTRL1 = 0 // Capture Parameters | ( 0 << 10 ) // Interlaced Format | ( 0 << 9 ) // No Vertical Ancillary | ( 0 << 8 ) // No Horizontal Ancillary | ( 1 << 6 ) // [2] Interrupt on Bottom Field | ( 0 << 4 ) // Raster | ( 0 << 3 ) // Y/C on seperate byte streams | ( 0 << 1 ) | ( 0 << 0 ); // Channel Disabled
channel1->regs->IMG_LINE_OFFSET = 1920; channel1->regs->HSIZE_CFG = ( 272 << 16 ) | ( 1920 << 0 ); channel1->regs->VSIZE_CFG0 = ( 1 << 16 ) | ( 21 << 0 ); channel1->regs->VSIZE_CFG1 = ( 561 << 16 ) | ( 564 << 0 ); channel1->regs->VSIZE_CFG2 = ( 584 << 16 ) | ( 1124 << 0 ); channel1->regs->VSIZE_CFG3 = ( 1125 ); |
2.4 TVP7002寄存器配置
对于TVP7002的配置比较复杂,需要参考TI官网上TVP7002的配置例程。在配置TVP7002之前,需要通过CPLD选通TVP7002的I2C通道并使能芯片,然后通过I2C配置TVP7002的各个I2C寄存器使其正常工作。在配置TVP7002为某种工作模式之前,需要先将TVP7002进行软件复位然后才开始配置。
TVP7002的寄存器配置如下所示。
/* TVP7002 - 1080i@60Hz - 33.75 Khz - 74.25Mhz - 20bit 4:2:2 - Embedded Syncs */ errors |= tvp7002_rset( 0x01, 0x89 ); // PLL DIVMSB 2200 errors |= tvp7002_rset( 0x02, 0x80 ); // PLL DIVLSB errors |= tvp7002_rset( 0x03, 0x98 ); // PLL CONTROL errors |= tvp7002_rset( 0x04, 0x80 ); // PHASE SEL(5) CKDI CKDI DIV2
errors |= tvp7002_rset( 0x05, 0x32 ); // CLAMP START errors |= tvp7002_rset( 0x06, 0x20 ); // CLAMP WIDTH errors |= tvp7002_rset( 0x07, 0x60 ); // HSYNC OUTPUT WIDTH - 96 //errors |= tvp7002_rset( 0x0e, 0x20 ); // SYNC CONTROL HSout+ errors |= tvp7002_rset( 0x0e, 0x1b );
errors |= tvp7002_rset( 0x0f, 0x2e ); // PLL and CLAMP CONTROL errors |= tvp7002_rset( 0x10, 0x5d ); // SOG Threshold-(YPbPr Clamp) errors |= tvp7002_rset( 0x11, 0x47 ); // SYNC SEPERATOR THRESHOLD //errors |= tvp7002_rset( 0x12, 0x00 ); // PRE_COAST errors |= tvp7002_rset( 0x12, 0x01 ); // PRE_COAST errors |= tvp7002_rset( 0x13, 0x00 ); // POST_COAST errors |= tvp7002_rset( 0x15, 0x47 ); // Output Formatter, 64-960, embedded syncs errors |= tvp7002_rset( 0x16, 0x01 ); // MISC Control errors |= tvp7002_rset( 0x17, 0x00 ); // Outputs enabled errors |= tvp7002_rset( 0x18, 0x01 ); // T-SW disabled, blank off, CSC disabled, FID, SOG, CLK polarity=invert errors |= tvp7002_rset( 0x19, 0x00 ); // INPUT MUX SELECT CH1 selected (BNC ) errors |= tvp7002_rset( 0x1a, 0x67 ); // SOG Filter(10Mhz) and CLP, INT REF CLK, INPUT MUX SELECT HSYNC_B and VSYNC_B selected
errors |= tvp7002_rset( 0x21, 0x08 ); // HSOUT START errors |= tvp7002_rset( 0x22, 0x00 ); // Macrovision support errors |= tvp7002_rset( 0x26, 0x80 ); // ALC Enable errors |= tvp7002_rset( 0x28, 0x53 ); // AL FILTER Control errors |= tvp7002_rset( 0x2a, 0x07 ); // Enable FINE CLAMP CONTROL errors |= tvp7002_rset( 0x2b, 0x00 ); // POWER CONTROL-SOG ON errors |= tvp7002_rset( 0x2c, 0x50 ); // ADC Setup errors |= tvp7002_rset( 0x2d, 0x00 ); // Coarse Clamp OFF errors |= tvp7002_rset( 0x2e, 0x80 ); // SOG Clamp ON errors |= tvp7002_rset( 0x31, 0x5a ); // ALC PLACEMENT
errors |= tvp7002_rset( 0x34, 0x02 ); // Macrovision Stripper Width //errors |= tvp7002_rset( 0x3e, 0x04 ); errors |= tvp7002_rset( 0x3f, 0x01 ); // Input B/W
errors |= tvp7002_rset( 0x40, 0x06 ); // AVID Start 262 (236+26) 27-1 for SOG filter differnence errors |= tvp7002_rset( 0x41, 0x01 ); // AVID Start errors |= tvp7002_rset( 0x42, 0x8a ); // AVID Stop 2186 (AVID start + 1920 + 4) errors |= tvp7002_rset( 0x43, 0x08 ); // AVID Stop
errors |= tvp7002_rset( 0x44, 0x02 ); // VBLK F0 Offset errors |= tvp7002_rset( 0x45, 0x02 ); // VBLK F1 Offse errors |= tvp7002_rset( 0x46, 0x16 ); // VBLK F0 Duration errors |= tvp7002_rset( 0x47, 0x17 ); // VBLK F1 Duration |
3 使用Matlab显示高清视频图像
在CCS中运行程序,当VPIF把一帧视频数据存储到DDR2SDRAM中之后,可以通过CCS的Load/Save Utility功能将该帧数据传输到上位机,然后通过Matlab显示出来,以判断采集到的视频数据是否正确。
在使用Matlab读取存储到上位机的视频帧数据时,特别需要注意数据存储的顺序,否则会读取出混乱的图像。VPIF存储到DDR2上数据格式如下所示。
YYYYYY……YYYYYY |
top field |
CbCrCbCr……CbCrCbCr |
top field |
YYYYYY……YYYYY |
bottom field |
CbCrCbCr……CbCrCbCr |
bottom field |
最开始是top field的亮度信号,然后是色度信号,接下来是bottom field的亮度信号和色度信号。所以在读取的时候需要按照以下顺序来读。
for i = 1:ver_t yt(i,:) = fread(fid, hor, 'uint8' ); end for i = 1:ver_t ct(i,:) = fread(fid, hor, 'uint8' ); end for i = 1:ver_b yb(i,:) = fread(fid, hor, 'uint8' ); end for i = 1:ver_b cb(i,:) = fread(fid, hor, 'uint8' ); end |
最终,使用Matlab显示的图像如图 9和图 10所示。
图 9 高清图像示例1
图 10 高清图像示例2