摘要
本篇主要讲述关于视频驱动的采集与显示的Mini-Driver在SEED-VPM642板卡上的应用。这个驱动程序符合DSP/BIOS的驱动模型。在TMS320DM642与存贮器之间采用EDMA进行数据的交换。为了代码容易维护,这个驱动由数据管理与视频编解码器件控制两部分组成。
驱动程序的特点:
多对象驱动(一个驱动程序可以控制多路的编解码电路); 采集驱动支持以下的模式:
¾ 双通路的8/10位的内嵌时基与外部同步的BT.656格式输出 ¾ 四通路的8/10位的内嵌时基的BT.656格式输出。 显示驱动支持以下的模式:
¾ 8/10位的内嵌时基的BT.656格式输入; ¾ 8/10位的使用外部同步的BT.656格式输入; 支持视频口的所有的事件中断;
允许用户通过应用程序的配置参数来设定驱动中视频帧的数据缓冲区。
1. 概述
这里所说的器件驱动程序实际上是IOM Mini-driver的一部分。它是处在二层器件驱动程序模型的底层,其上层是FVID模块,这是一个经过简单包装的DSP/BIOS的GIO型类驱动。像GIO型的类驱动为不同的Mini-driver一系列通用且独立的API函数与服务一样,FVID也为视频帧的采集与显示提供了定制的API。相关的内容,请参看附录B中有关FVID详细说明。
图一说明了DSP/BIOS器件驱动程序的结构,关于IOM、GIO、SIO/DIO和PIP/PIO的器件驱动模型参看相关的说明。
图一:DSP/BIOS驱动分层模型
图二说明了SEED-VPM642视频采集与显示的Mini-driver驱动程序的结构图,为了使SEED-VPM642视频采集与显示的Mini-driver驱动程序的代码有最大的重复使用能力,将其分为数据管理与视频编解码器件控制两部分。与其它将用户板上器件控制程序直接放在Mini-driver中不同的是,在视频采集与显示的Mini-driver中是通过外部器件控制接口(EDC)把视频编解码器件的控制集成到Mini-driver中的。这样使我们的视频采集与显示的Mini-driver能适应不同的视频编解码器件。当更换不同器件时,只须更改EDC部分即可,其它的部分可保持不变。
图二:采集与显示驱动分层模型
本文主要描述SEED-VPM642视频采集与显示Mini-driver的数据管理与器件控制两部分。数据管理部分是采用EDMA技术完成对视频口的写入与读出。器件控制部分在采集驱动里完成对TVP5150AM的初始化与配置;在显示驱动里,完成对SAA7121的初始化与配置。器件控制部分(EDC)使视频编解码器与DM642的视频口配合工作,完成指定视频数
据格式的采集与显示。例如,TVP5150根据应用程序的需要可以配置成为NTSC制式或PAL制式的采集。同时,视频口也应配置成为相同的模式。
器件控制接口部分程序运行前需要SEED-VPM642调用SEED-VPM642板级支持库(seedvpm642_bsl.lib)中的初始化程序SEEDVPM642_init()对EMI与I2C总线控制器进行初始化。因此,正确调用视频采集与显示库,需要在编程时同时连接seedvpm642_bsl.lib与seedvpm642_vport.l64这两个库。
2.
2.1
使用规则
驱动程序在DSP/BIOS中的配置
为了使用采集与显示的器件驱动,必须在DSP/BIOS配置工具中加入相应的配置设备实体。关于如何使用DSP/BIOS来配置设备实例的详细内容可参看< Init function:这个驱动无初始化的函数 Function table ptr:_VPORTCAP_Fxns Function table type: IOM_Fxns Device id: 0~3,指定是SEEDVPM642系统内哪一通路的采集 Device params ptr:这是一个可选项,它是一个指向VOPRT_PortParams结构的 指针,这个结构定义在vport.h的头文件中。这个结构是用来设定视频口与解码器件参数的。如果将这个指针设为NULL,则应用程序需要另外调用FVID_control来初始化视频口与解码器件。关于这个结构设置的例子,可以在seedvpm642_vcapparamsPAL_EMBEDDED.c中看到。 Device global data ptr:此参数在驱动中未使用。 下面是显示驱动在DSP/BIOS中设备实体设置参数: Init function:这参数驱动程序未使用。 Function talbe ptr:_VPORTDIS_Fxns Function table type: IOM_Fxns Device id: 在SEED-VPM642设为0,使用视频口0 Device params ptr:这个参数的设置与采集驱动是一致的 Device global data ptr:此参数在驱动中未使用。 2.1.1 视频口参数 typedef struct VPORT_PortParams { Bool dualChanEnable; Bool dualChanEnab; Uns vc1Polarity; Uns vc2Polarity; Uns vc3Polarity; EDC_Fxns* edcTbl[2]; }VPORT_PortParams; dualChanEnable:是否使能视频口的双通路模式(TRUE或FALSE) vc1Polarity: 视频口管脚vctrl1是高有效还是低有效,其值为: ¾ VPORT_POLARITY_ACTIVE_HIGH:高有效; ¾ VPORT_POLARITY_ACTIVE_LOW: 低有效; Vc2 Polarity: 视频口管脚vctrl2是高有效还是低有效,其值为: ¾ VPORT_POLARITY_ACTIVE_HIGH:高有效; ¾ VPORT_POLARITY_ACTIVE_LOW: 低有效; Vc3Polarity: 视频口管脚vctrl3是高有效还是低有效,其值为: ¾ VPORT_POLARITY_ACTIVE_HIGH:高有效; ¾ VPORT_POLARITY_ACTIVE_LOW: 低有效; edcTbl[2]:指向器件控制接口(EDC)的两个指针队列,每一个通路有一地址, 当只使用一个时,另一个设为NULL。 2.1.2 采集通路参数 typedef struct { Int cmode; Int fldOp; Int scale; Int resmpl; Int bpk10Bit; Int hCtRst; Int vCtRst; Int fldDect; Int extCtl; Int fldInv; Uint16 fldXStrt1; Uint16 fldYStrt1; Uint16 fldXStrt2; Uint16 fldYStrt2; Uint16 fldXStop1; Uint16 fldYStop1; Uint16 fldXStop2; Uint16 fldYStop2; Uint16 thrld; Int numFrmBufs; Int alignment; Int mergeFlds; Int segId; Int edmaPri; Int irqId; Bool autoSyncEnable; } VPORTCAP_Params; 上面结构中定义的每一位直接映射射到视频采集控制寄存器。未定义的位保持复位进的默认值,下面是这些定义的详细说明: Cmode:采集的模式,下面是在Vport.h内定义的可能的值,在SEEDVPM642 中只能采用第一种模式。 ¾ VPORT_MODE_BT656_8BIT ¾ VPORT_MODE_BT656_10BIT ¾ VPORT_MODE_RAW_8BIT ¾ VPORT_MODE_RAW_10BIT ¾ VPORT_MODE_YC_8BIT ¾ VPORT_MODE_YC_10BIT ¾ VPORT_MODE_RAW_16BIT ¾ VPORT_MODE_RAW_20BIT fldOp: 帧或场的操作模式。下面是在Vport.h内定义的可能的值: ¾ VPORT_FLDOP_FLD1 ¾ VPORT_FLDOP_FLD2 ¾ VPORT_FLDOP_FRAME ¾ VPORT_FLDOP_PROGRESSIVE scale: 水平½缩小使能。下面是在Vport.h内定义的可能的值: ¾ VPORT_SCALING_DISABLE ¾ VPORT_SCALING_ENABLE resmpl: 将每行色度由4:2:2变换4:2:0使能. 下面是在Vport.h内定义的可能的值: ¾ VPORT_RESMPL_DISABLE ¾ VPORT_RESMPL_DISABLE bpk10Bit: 10位视频采集模式, 下面是在Vport.h内定义的可能的值: ¾ VPORTCAP_BPK_10BIT_ZERO_EXTENDED ¾ VPORTCAP_BPK_10BIT_SIGN_EXTENDED ¾ VPORTCAP_BPK_10BIT_DENSE hCtRst: 行(水平方向)计数复位模式。下面是在Vport.h内定义的可能的值: ¾ VPORTCAP_HRST_EAV ¾ VPORTCAP_HRST_START_HBLK ¾ VPORTCAP_HRST_START_HSYNC ¾ VPORTCAP_HRST_SAV ¾ VPORTCAP_HRST_END_HBLK ¾ VPORTCAP_HRST_END_HSYNC vCtRst: 场(垂直方向)计数复位模式. 下面是在Vport.h内定义的可能的值: ¾ VPORTCAP_VRST_START_VBLK ¾ VPORTCAP_VRST_START_VSYNC ¾ VPORTCAP_VRST_END_VBLK ¾ VPORTCAP_VRST_END_VSYNC ¾ VPORTCAP_VRST_EAV_V1 ¾ VPROTCAP_VRST_EAV_V0 fldDect: 场侦测使能,此项功能仅在使用外部同部时使用。当使能时,需要确定场 侦测的方式。一般是由H-Sync与V-Sync的关系或由Field输入管脚来确定。下面是在Vport.h内定义的可能的值: ¾ VPORTCAP_FLDD_ENABLE ¾ VPORTCAP_FLDD_ENABLE extCtl: 外部同步使能。下面是在Vport.h内定义的可能的值: VPORTCAP_EXC_DISABLE VPORTCAP_EXC_ENABLE fldInv: 场反转使能。下面是在Vport.h内定义的可能的值: ¾ VPORTCAP_FINV_DISABLE ¾ VPORTCAP_FINV_ENABLE fldXStrt1: 第一场起始像素点横坐标 其值大于等0 fldYStrt1: 第一场起始像素点纵坐标 其值大于等0 fldXStrt2: 第二场起始像素点横坐标 其值大于等0 fldYStrt2: 第二场起始像素点纵坐标 其值大于等0 fldXStop1: 第一场起始像素点横坐标 其值大于等fldXStrt1 fldYStop1: 第一场起始像素点纵坐标 其值大于等fldYStrt1 fldXStop2: 第二场起始像素点纵坐标 其值大于等fldXStrt2 fldYStop2: 第二场起始像素点纵坐标 其值大于等fldYStrt2 thrld: 设定产生DMA中断的门槛,以双字节以单位 numFrmBufs:设定驱动程序中采集缓冲区的个数 alignment: 采集缓冲区的对齐长度 mergeFlds: 指定场在缓冲区中的存放方式,可以将两场分别存放,也可以排成逐 行方式存放(两场交叉存放)。下面是在Vport.h内定义的可能的值: ¾ VPORT_FLDS_MERGED ¾ VPORT_FLDS_SEPARATED SegId: DSP/BIOS 存贮空间ID, 驱动用来分配视频帧的缓冲区。 edmaPri: EDMA的优先级 irqId: EDMA中断安排 autoSyncEnable:是否使能断帧自动同步功能。下面是在Vport.h内定义的可能的 值: ¾ TRUE ¾ FALSE 2.1.3 显示通路参数 typedef struct { Int dmode; Int fldOp; Int scale; Int resmpl; Int defValEn; Int bpk10Bit; Int vctl1Config; Int vctl2Config; Int vctl3Config; Int extCtl; Uint16 frmHSize; Uint16 frmVSize; Int16 imgHOffsetFld1; Int16 imgVOffsetFld1; Uint16 imgHSizeFld1; Uint16 imgVSizeFld1; Int16 imgHOffsetFld2; Int16 imgVOffsetFld2; Uint16 imgHSizeFld2; Uint16 imgVSizeFld2; Uint16 hBlnkStart; Uint16 hBlnkStop; Uint16 vBlnkXStartFld1; Uint16 vBlnkYStartFld1; Uint16 vBlnkXStopFld1; Uint16 vBlnkYStopFld1; Uint16 vBlnkXStartFld2; Uint16 vBlnkYStartFld2; Uint16 vBlnkXStopFld2; Uint16 vBlnkYStopFld2; Uint16 xStartFld1; Uint16 yStartFld1; Uint16 xStartFld2; Uint16 yStartFld2; Uint16 hSyncStart; Uint16 hSyncStop; Uint16 vSyncXStartFld1; Uint16 vSyncYStartFld1; Uint16 vSyncXStopFld1; Uint16 vSyncYStopFld1; Uint16 vSyncXStartFld2; Uint16 vSyncYStartFld2; Uint16 vSyncXStopFld2; Uint16 vSyncYStopFld2; Uint8 yClipLow; Uint8 yClipHigh; Uint8 cClipLow; Uint8 cClipHigh; Uint8 yDefVal; Uint8 cbDefVal; Uint8 crDefVal; Int rgbX; Int incPix; Uint16 thrld; Int numFrmBufs; Int alignment; Int mergeFlds; Int segId; Int edmaPri; Int irqId; } VPORTDIS_Params; dmode: 显示模式。在SEEDVPM642中只支持第一种值下面是在Vport.h内定义 的可能的值: ¾ VPORT_MODE_BT656_8BIT ¾ VPORT_MODE_BT656_10BIT ¾ VPORT_MODE_RAW_8BIT ¾ VPORT_MODE_RAW_10BIT ¾ VPORT_MODE_YC_8BIT ¾ VPORT_MODE_YC_10BIT ¾ VPORT_MODE_RAW_16BIT ¾ VPORT_MODE_RAW_20BIT fldOp: 场与帧的操作模式下面是在Vport.h内定义的可能的值: ¾ VPORT_FLDOP_FLD1 ¾ VPORT_FLDOP_FLD2 ¾ VPORT_FLDOP_FRAME ¾ VPORT_FLDOP_PROGRESSIVE scale: 行(水平方向)的2倍放大功能使能。下面是在Vport.h内定义的可能的值: ¾ VPORT_SCALING_DISABLE ¾ VPORT_SCALING_ENABLE resmpl:每一行(水平方向)色度由4:2:0 变换成 4:2:2的使能. 下面是在Vport.h 内定义的可能的值: ¾ VPORT_RESMPL_DISABLE ¾ VPORT_RESMPL_DISABLE defValEn: 默认值输出使能。当使能时,在非消隐区显示默认值。下面是在Vport.h 内定义的可能的值: ¾ VPORTDIS_DEFVAL_DISABLE ¾ VPORTDIS_DEFVAL_ENABLE bpk10Bit: 10位数据显示模式. 下面是在Vport.h内定义的可能的值: ¾ VPORTDIS_BPK_10BIT_NORMAL ¾ VPORTDIS_BPK_10BIT_DENSE vctl1Config: VCTL1输出功能选择。下面是在Vport.h内定义的可能的值: ¾ VPORTDIS_VCTL1_HSYNC ¾ VPORTDIS_VCTL1_HBLNK ¾ VPORTDIS_VCTL1_AVID ¾ VPORTDIS_VCTL1_FLD vctl2Config: VCTL2输出功能选择。下面是在Vport.h内定义的可能的值: ¾ VPORTDIS_VCTL2_VSYNC ¾ VPORTDIS_VCTL2_VBLNK ¾ VPORTDIS_VCTL2_CSYNC ¾ VPORTDIS_VCTL2_FLD vctl3Config: VCTL3输出功能选择。下面是在Vport.h内定义的可能的值: ¾ VPORTDIS_VCTL3_CBLNK ¾ VPORTDIS_VCTL3_FLD extCtl: 外部控制使能,指定视频口是做为主模式还是从模式。当其为主模式时 VCTLx管脚为输出信号,当其为从模式时,这此管脚为输入,需要外部(例如视频编码器件)提供控制信号. 输出功能选择。下面是在Vport.h内定义的可能的值: ¾ VPORTDIS_EXC_DISABLE ¾ VPORTDIS_EXC_ENABLE frmHSize: 视频帧每行有多少像素,包括行消隐在内。 frmVSize: 视频帧有多少行,包括场消隐急在内。 imgHOffsetFld1: 第一场图像显示的行偏置,其计算是相对于每行的最后一个行消 隐像素位置。可以在行消隐时,使输出水平镜像. imgVOffsetFld1: 第一场图像显示的场偏置,其计算是相对每场的最后一个消隐行 位置。可以在场消隐时,使输出垂直镜像。 imgHSizeFld1: 第一场图像显示每行宽度。 imgVSizeFld1: 第一场图像显示的行数。 imgHOffsetFld2: 第二场图像显示的行偏置,其计算是相对于每行的最后一个行消 隐像素位置。可以在行消隐时,使输出水平镜像. imgVOffsetFld2: 第二场图像显示的场偏置,其计算是相对每场的最后一个消隐行 位置。可以在场消隐时,使输出垂直镜像。 imgHSizeFld2: 第二场图像显示每行宽度。 imgVSizeFld2: 第二场图像显示的行数。 hBlnkStart: 每行(水平方向)的消隐开始的像素位置。 hBlnkStop: 每行(水平方向)的消隐结束的像素位置。 vBlnkXStartFld1: 第一场场消隐开始的行(水平方向)的像素位置 vBlnkYStartFld1: 第一场场消隐开始的哪一行(垂直方向) vBlnkXStopFld1: 第一场场消隐结束的行(水平方向)的像素位置 vblnkYStopFld1: 第一场场消隐结束的哪一行(垂直方向) vBlnkXStartFld2: 第二场场消隐开始的行(水平方向)的像素位置 vBlnkYStartFld2: 第二场场消隐开始的哪一行(垂直方向) vBlnkXStopFld2: 第二场场消隐结束的行(水平方向)的像素位置 vblnkYStopFld2: 第二场场消隐结束的行(水平方向)的像素位置 xStartFld1: 第一场显示输出第一行的第一个像素点的位置。 yStartFld1: 第一场显示输出的行数。 xStartFld2: 第二场显示输出第一行的第一个像素点的位置。 yStartFld2: 第二场显示输出的行数。 hSyncStart: 每行行同步有效开始的像素位置。 hSyncStop: 每行行同步有效结束的像素位置。 vSyncXStartFld1: 第一场场同步开始的像素的位置(水平方向)。 vSyncYStartFld1: 第一场场同步开始的行数(垂直方向)。 vSyncXStopFld1: 第一场场同步结束的像素的位置(水平方向)。 vSyncYStopFld1: 第一场场同步结束的行数(垂直方向)。 vSyncXStartFld2: 第二场场同步开始的像素的位置(水平方向)。 vSyncYStartFld2: 第二场场同步开始的行数(垂直方向)。 vSyncXStopFld2: 第二场场同步结束的像素的位置(水平方向)。 vSyncYStopFld1: 第一场场同步结束的行数(垂直方向)。 yClipLow: 指定Y的最低值。 yClipHigh: 指定Y的最高值。 cClipLow: 指定CbCr的最低值。 cClipHigh: 指定CbCr的最高值。 yDefVal: 指定Y的默认输出值。 cbDefVal: 指定Cb的默认输出值 crDefVal: 指定Cr的默认输出值 rgbX: 只在Raw模式下使用,用来使能连续的24/30RGB数据的输出。本系统未 使用。 incPix: 只在Raw模式下使用。本系统未使用。 thrld: 设定产生DMA中断的门槛,以双字节以单位。 numFrmBufs: 设置显示驱动使用的视频数据缓冲区的个数 alignment: 显示缓冲区的对齐长度 mergeFlds: 指定场在缓冲区中的存放方式,可以将两场分别存放,也可以排成逐 行方式存放(两场交叉存放)。下面是在Vport.h内定义的可能的值: ¾ VPORT_FLDS_MERGED ¾ VPORT_FLDS_SEPARATED SegId: DSP/BIOS 存贮空间ID, 驱动用来分配视频帧的缓冲区。 edmaPri: EDMA的优先级 irqId: EDMA中断安排 2.1.4 视频口全局中断程序接口 typedef struct VPORT_VIntCbParams { Int cbArg; VPORT_IntCallBack vIntCbFxn; Uint16 vIntMask; Uint16 vIntLine; Int irqId; } VPORT_VIntCbParams; cbArg: 中断回调函数的参数 vIntCBFxn: 指向中断回调函数的指针 vIntMask:设定可以产生全局中断的视频口的事件,其映射为视频口的中断使能寄 存器,其可能的值在vport.h列出: ¾ VPORT_INT_COVR: 采集FIFO覆盖中断 ¾ VPORT_INT_CCMP: 采集完成中断 ¾ VPORT_INT_SERR: 同步错误中断 ¾ VPORT_INT_VINT1: 第一场的场同步中断 ¾ VPORT_INT_VINT2: 第二场的场同步中断 ¾ VPORT_INT_SFD: 短帧中断 ¾ VPORT_INT_LFD: 长帧中断 ¾ VPORT_INT_STC: 系统时钟的中断 ¾ VPORT_INT_TICK: 时基中断 ¾ VPORT_INT_DUND: 显示FIFO覆盖中断 ¾ VPORT_INT_DCMP: 显示完成中断 ¾ VPORT_INT_DCNA: 显示完成未确认中断 irqId: 视频全局中断对应的中断号。 IntrMask:中断屏蔽,为ISR执行时使用。 2.1.5 显示驱动命令 以下是驱动程序在执行时,在vport.h中定义执行命令 VPORT_CMD_RESET: 复位视频口 VPORT_CMD_CONFIG_PORT: 配置视频口 VPORT_CMD_CONFIG_CHAN: 配置视频通路 VPORT_CMD_START: 开始采集或显示操作 VPORT_CMD_STOP: 停止采集或显示操作 VPORT_CMD_SET_VINTCB: 设置驱动程序的中断回调函数 VPORT_CMD_DUND_RECOVER: 强制显示驱动从under-run中恢复 VPORT_CMD_COVR_RECOVER: 强制采集驱动从over-run中恢复 2.2 2.2.1 驱动程序器件控制的参数 外部器件控制的接口(EDC) 在以上的图二中可以看出,在采集与显示的Mini-driver中,包含了以下两部分: 数据管理部分,这部分可以兼容系统内不同的编解码器,这种分的设置主要针对 DM64本身。和视频数据流的管理。 器件接口部分,这部分主要是配置用户选择的视频编解码器件,对其进行配置,并 与DM642的工作模式一致。这部分是用户在改变视频编解码器件时需要改变的。在SEED-VPM643系统中这部分工作已经进行了配制,故将其封装在库中。以下就其做简单说明。 为了使代码更改最小,修改时产生更少的错误,在器件接口部分实现了两个与驱动程序无缝的APIs接口。驱动程序通过APIs函数调用配置视频编解码器件,使其与视频口相配合。APIs接口是由三个函数及,一系列的命令组成。举例如下: /* EDC control commands */ #define EDC_CONFIG 0x00000001 #define EDC_RESET 0x00000002 #define EDC_START 0x00000003 #define EDC_STOP 0x00000004 #define EDC_GET_CONFIG 0x00000005 #define EDC_GET_STATUS 0x00000006 /* base of user defined commands */ #define EDC_USER 0x10000000 /* EDC return codes */ #define EDC_SUCCESS 0 #define EDC_FAILED −1 typedef void* EDC_Handle; /* * ======== EDC_Fxns ======== * edcOpen() required, open the device * edcClose() required, close the device * edcCtrl() required, control/query device */ typedef struct EDC_Fxns { EDC_Handle (*open)(String name, Arg optArg); Int (*close)(Ptr devHandle); Int (*ctrl)(Ptr devHandle, Uns cmd, Arg arg); } EDC_Fxns; 2.2.2 采集EDC接口函数及参数配制 typedef struct { TVP51XX_Mode videoMode; TVP51XX_AnalogFormat aFmt; int inputPort; I2C_Handle hI2C; } TVP51XX_ConfParams; videoMode:采集视频输出的格式,一些可能的值定义在TVP51XX.h中,列表如 下: typedef enum TVP51XX_Mode { TVP51XX_MODE_NTSC601, TVP51XX_MODE_NTSCSqp, TVP51XX_MODE_PAL601, TVP51XX_MODE_PALSqp, TVP51XX_MODE_USER }TVP51XX_Mode; aFmt:模拟视频输入的格式,一些可能的值定义在TVP51XX.h中,列表如下: typedef enum TVP51XX_AnalogFormat { TVP51XX_AFMT_COMPOSITE, TVP51XX_AFMT_SVIDEO, TVP51XX_AFMT_RGB, TVP51XX_AFMT_YPBPR } TVP51XX_AnalogFormat; inputPort:输入的通路数,在SEED-VPM642系统内采用单路输入,其值为1。 hI2C:已在seedvpm642_bsl的初始函数中打开的DM642的IIC的控制器句柄。 2.2.3 采集EDC接口函数及参数配制 typedef struct { SAA7121_AnalogFormat aFmt; SAA7121_Mode mode; SAA7121_InputFormat iFmt; Bool enableSlaveMode; Bool enableBT656Sync; I2C_Handle hI2C; } SAA7121_ConfParams; aFmt:SAA7121模拟输出的形式,一些可能的值在SAA7121.h中进行了定义, 在SEED-VPM642中,只支持SVIDEO, COMPOSITE两种。列表如下: typedef enum SAA7121_AnalogFormat { SAA7121_AFMT_SVIDEO = 0, SAA7121_AFMT_RGB = 1, SAA7121_AFMT_YPBPR = 1, SAA7121_AFMT_COMPOSITE = 2 } SAA7121_AnalogFormat; mode:SAA7121输出支持的制式。一些可能的值在SAA7121.h中进行了定义, 列表如下: typedef enum { SAA7121_MODE_NTSC720, SAA7121_MODE_PAL720, }SAA7121_Mode; iFmt:输入视频数据流的格式。一些可能的值在SAA7121.h中进行了定义,列表 如下: typedef enum SAA7121_InputFormat { SAA7121_IFMT_YCBCR422_NONEINTERLACED, SAA7121_IFMT_YCBCR422_INTERLACED }SAA7121_InputFormat; enableSlaveMode:SAA7121的控制模式。在SEED-VPM642中采用从模式,此 项设置为TRUE。一些可能的值在SAA7121.h中进行了定义,列表如下: ¾ TRUE:为从模式,DM642为主控。 ¾ FALSE:SAA7121为主模式。 enableBT656Sync:SAA7121的同步控制。此顶在SEED-VPM642中未采用。 hI2C:已在seedvpm642_bsl的初始函数中打开的DM642的IIC的控制器句柄。 2.2.4 在FVID_create()函数中的命名规则 由于DM642可以进行双通路的采集,并且可以通过EDC接口配置不同的视频编解码器件。因此必须有一种方法把这些信息从应用程序传递给视频采集与显示驱动。这个规则是通过调用FVID_create()函数来实现传递的。这个函数的第一个参数即为包含这一规则的字符串型的参数,取名为name。下面介绍这一字符串的命名规则: 使用采集驱动时,字符串包含3个子字符串,以反斜杠“/”区分。例如 “/VP0CAPTURE/A/0”。 字符串的第一部分是在DSP/BIOS的.cdb文件中命名的驱动名称。GIO类型的类 驱动通过这个字符串关联的 Device ID 来确定使用哪个视频口。 字符串的第二部分说明是使用视频口的A通路,还是B通路。 字符串的第三部分是可选反,如果被指定,用来指定是使用的第几个视频口。 显示驱动中的命名规则与采集中使用的是一致的。例如:\"/VP0DISPLAY/A/0\"。 3. 采集与显示驱动程序的结构 这一节主要介绍驱动程序的设计与执行。驱动程序使用不同DSP/BIOS与CSL库的模块(参看附录A)。关这两部分的内容可参看文档TMS320C6000 DSP/BIOS Application Programming Interface (literature number SPRU403) and TMS320C6000 Chip Support Library API Reference Guide (literature number SPRU401)。有关EDMA的详细内容可以参看文档TMS320C6000 Peripherals Reference Guide (literature number SPRU190)。有关视频口的详细内容可以参看文档TMS320C64x DSP Video Port/ VCXO Interpolated Control (VIC) Port Reference Guide (literature number SPRU629)。 3.1 原理框图 图三:显示驱动的原理框 上图说明了显示驱动的原理。在显示操作中,数据从位于存贮空间的视频帧的数据缓冲区通过EDMA传递到视频口的FIFO内。视频口再将这些数据通过外部的Encoder送至显示屏。当每一帧的数据从存贮空间传视频口后,触发EDMA中断。这个中断是整个程序的关键,被驱动程序用做下以目的: 帧缓冲区的管理 EDMA的重装 通过回调函数通知类驱动空的帧缓冲区已经可以被应用程序所填写。 视频口的全局中断是可选的。它可以使应用程序处理视频口的错误或是同步问题。 采集驱动除了在数据方向上与显示驱动相反外,其它均是一致的。 3.2 缓冲区的管理 包含视频数据的帧缓冲区是由驱动程序初始化并进行管理的。驱动程序在运行时,至少需要配置3个帧数据缓冲区。驱动程序将根据通数参数来计算帧缓冲区的大小。例如,一整帧的PAL帛的视频帧的大小为720X576X2。但如果,缩小1/2被使能,缓冲区的大小则被减 半。 通过FVID_alloc(),FVID_free(),FVID_exhange()函数,帧缓冲区可以在应用程序与驱动之间进行交换。然而对于显示与采集来说,其对帧缓冲区的处理办法是不一致的。具体说明如图四与图五。 图四:采集驱动的缓冲区管理 在采集过程中,所有的帧缓冲区都被初始化的状态是处于空队列内,并且驱动程序使其进行循环。其说明见图4(a)。 当应用程序调用FVID_alloc()时,将驱动程序中最新的一个帧数据缓冲取出,驱动程序命名剩下的缓冲区进行循环。其说明从图4(a)到4(b)、从4(b)到4(e)。 当程序调用FVID_free()时,一个空的帧数据缓冲区从应用程序返回驱动程序的空队列中,其说明从图4(b)到4(a)、从4(e)到4(b)。 当程序谳用FVID_exhange()时,一个空的帧数据缓冲区从应用程序返回驱动程序的空队列中,同时,将驱动程序中最新的一个帧数据缓冲取出。其作用相当于顺序调用FVID_free()与FVID_alloc()。其说明从图4(b)到4(c)、从4(c)到4(d)。 图五:显示驱动的缓冲区管理 在显示过程中,在其初始化时,除了一个帧缓冲区处于输出队列中,其它的都准备由应用程序进行抓取。驱动程序重复的显示处于输出队列中的帧缓冲区。共说明如图5(a)。 当应用程序调用FVID_alloc()时,在当前的帧显示缓冲区正还在显示时,从显示驱动获取一个帧缓冲区并开始填写要显示的数据。其说明如5(b)与5(d)。 当应用程序调用FVID_Free()时,和序将已经填好数据的帧缓冲区还给驱动程序。驱动程序在前一个显示帧缓冲区显示结束后将按顺序将其做为当前的显示帧。其说明从5(b)到5(c)到5(d)。 当程序调用FVID_exchange()时,把已填好数据的缓冲区还给驱动程序,并从驱动程序代回一个空的帧缓冲区。共做用相当于顺序调用FVID_free()与FVID_alloc()。其说明从5(d)到5(e)。 3.3 Cache的一致性 确保Cache的一致性是应用程序的责任,驱动在这一点上未做任何的处理。这是因为数据主要是在高速的片上SRAM与片外较低的SD-RAM之间通过EDMA进行传输。这比CPU获取数据要快得多。当算法使用乒乓机制时,可以使CPU的执行与EDMA的传送同时进行。从而掩藏了数据的搬移过程。在帧缓冲区的边界与Cache的边界一致情况下,Cache的刷新与清空操作是可以被避免的。 然而,当应用程驐直接使用这些帧缓冲区时,应用程序必须刷新与清空Cache,来确保其一致性。因为当CPU通过Cache获取数据时,EDMA正通过EMIF从片外的SDRAM搬运数据。 4. 视频采集与显示驱协的使用约束 此驱动程序不支持下列模式: 原始数据的采集 双通路同步的原始数据显示 两个视频口的同步 MPEG格式的数据流的采集。 5. 参考资料 以下的文档均可以在http://www.ti.com上获取 1. DSP/BIOS Driver Developer’s Guide (SPRU616) 2. TMS320C64x DSP Video Port/ VCXO Interpolated Control (VIC) Port Reference Guide (SPRU629) 3. TMS320C6000 DSP/BIOS Application Programming Interface (SPRU403) 4. TMS320C6000 Chip Support Library API Reference Guide (SPRU401) 5. TMS320C6000 Peripherals Reference Guide (SPRU190) 附录A Device Driver Data Sheet A.1 驱动程序的名称 Seedvpm642_vport2.1.l64. A.2 使用到的DSP/BIOS模块 HWI – 硬件中断管理器 QUE – 队列管理器 IOM – I/O 管理器 A.3 使用到的DSP/BIOS对象 QUE_Obj:队列对象 A.4 使用到的CSL模块 EDMA 模块 IRQ 模块 I2C 模块 VP 模块 A.5 使用到的CPU 中断 EDMA interrupt Video Port interrupt A.6 使用到的外设 EDMA EMIF I2C Video Port A.7 最大的中断延时(显示/采集) 89/71 cycles A.8 存贮空间的使用 表A−1. 驱动程序对存贮空间的占用 (显示/采集) 附录B FVID APIs函数接口 B.1 概述 FVID模块是为使基于DSP/BIOS应用程序操作视频帧数据采集与显示的一组API接口。FVID是在GIO类驱动的基础上进行了简单的封装,提供应用程序与视频数据之间定制的接口。有关DSP/BIOS设备驱动模型和GIO类驱动更多的信息,参看以下的说明。 FVID设备驱的API与那些需要由应用程序自已管理数据缓冲区的驱动程序是不一样的。绝大多数DSP/BIOS设备驱动程序希望应用程序初始化数据缓冲区,并将指向数据缓冲区的地址指针传给驱动程序,完成数据的输入与输出。FVID与视频采集与显示的Mini-driver工作正好相反。它是由设备驱动进行初始化并管理数据缓冲区。这种方法的目的是为了解决视频系统中的高速运行的大容量,专一的数据缓冲区的管理。这些数据缓冲区是存在系统的堆内的,也是使用这种方法才能更好的进行控制。由于缓冲区的大小、位置与状态都是在驱动程序内进行处理的,驱动程序可以更好的管理数据缓冲区。 基于帧的视频系统都具多数据缓冲的特点。双数据缓冲一般是这样安排:一个数据缓冲区将数据与视频编解码器件之间进行传送,另一个由应用程序进行处理。两个数据缓冲区是在帧同步时进行交换的。三缓冲的安排可以使应用程序无需等待帧同步的情况下获取一个数据缓冲区。在采集与显示驱动中,一般采用三缓冲的安排。 B.2 FVID的APIs 通过以上的介绍可知,采集与显示驱动程序初始化并管理视频的帧缓冲区,应用程序则是在需要的时候获取这些缓冲区。FVID的APIs首要的任务就是管理这些驱动程序在驱动与应用程序之间所有权的分配。FVID的两个核心调用如下: FVID_alloc 使应用程序获取一个视频的帧缓冲区 FVID_exchange 把应用程序所拥有的缓冲区,与驱动程序所拥有的缓冲区进行交 换 当驱动程被初始化后,应用程序首先使用FVID_alloc获取一个数据缓冲区,然后就可以调用FVID_exchange在应用程序与驱动程序之间进行缓冲区的交换。 FVID接口与DSP/BIOS完全兼容的。每一个通路的FVID产生一个独立的同步体。当进行获取与交换视频缓冲区时,可以进行阻塞或非阻塞处理。这由用户在初始化同步体时是否指定了其超时参数决定的。 下面是一个简单的例子,说明了应用程序获取采集数据,并将在一定的器件上进行显示。 #include /* 当Main()结束时DSP/BIOS 开始运行 */ } /* 视频处理任务 */ void tskVDisplay() { /* 采集与显示的设备对象 */ GIO_Handle capChan, disChan; /* 采集与显示的帧缓冲区 */ FVID_Frame *capFrameBuf, *disFrameBuf; /* 产生并初始化FVID的通路对象*/ capChan = FVID_create(”/vcap”, IOM_INPUT, NULL, (Ptr)&capParams, NULL); disChan = FVID_create(”/vdis”, IOM_OUTPUT, NULL, (Ptr)&disParams, NULL); /* 应用程序获取第一个采集帧与显示帧*/ FVID_alloc(capChan, &capFrameBuf); FVID_alloc(disChan, &disFrameBuf); while(1) { /* 将采集帧缓冲数据,拷贝到显示帧缓冲区,并进行交换 */ FrameDataCopy(capFrameBuf, disFrameBuf); FVID_exchange(capChan, &capFrameBuf); FVID_exchange(disChan, &disFrameBuf); } } B.3 API说明 B.3.1 函数 FVID定义的API函数列表如下: FVID_alloc. 应用程序获取一个缓冲区 FVID_control. 应用程序送一个控制命令到mini-driver. FVID_create. 应用程序产生一个FVID实体对象 FVID_delete. 应用程序删除一个FVID实体对象 FVID_exchange. 应用程序与驱动程序交换数据缓冲区 FVID_free. 应用程序归还驱动程序数据缓冲区 B.3.2 相关的数据类型及数据结构 /* 定义非交错帧的结构 */ typedef struct FVID_IFrame { unsigned char* y1; unsigned char* cb1; unsigned char* cr1; unsigned char* y2; unsigned char* cb2; unsigned char* cr2; }FVID_IFrame; /*连续帧的结构 */ typedef struct FVID_PFrame { unsigned char* y; unsigned char* cb; unsigned char* cr; } FVID_PFrame; /* 原始数据帧,可以是RGB、单色、或其他类型*/ typedef struct FVID_RawIFrame { unsigned char* buf1; unsigned char* buf2; } FVID_RawIFrame; typedef struct FVID_RawPFrame { unsigned char* buf; } FVID_RawPFrame; /* FVID帧缓冲区结构 */ typedef struct FVID_Frame { QUE_Elem queElement; /* 必需的队列对象*/ Union { FVID_IFrame iFrm; /* y/c frame buffer */ FVID_PFrame pFrm; /* y/c frame buffer */ FVID_RawIFrame riFrm; /* raw frame buffer */ FVID_RawPFrame rpFrm; /* raw frame buffer */ } frame; } FVID_Frame; B.4 函数调用 FVID_alloc Syntax Parameters Return Value Description Constraints Example FVID_control Syntax Parameters Return Value Description Constraints Example 应用程序获取一个缓冲区 status = FVID_alloc (fvidChan, bufp); FVID_Handle fvidChan /* 设备实体的句柄 */ Ptr bufp /* 指向获取到的缓冲区的指针*/ Int status /* 如果成功返回IOM_COMPLETED */ 当应用程序调用FVID_alloc时,驱动将一个帧缓冲区交给应用程序。这个API函数对应至Mini-driver中的一个mdSubmit()函数调用。 fvidChan参数是视频驱动程序的一个通路句柄。是在调用VID_create时产生的bufp参数是输出参数,指向驱动程序提交的FVID_Frame结构缓冲区的指针。 FVID_alloc调用成功后返回IOM_COMPLETED。如果请求被mini-driver排入队列,将返回IOM_PENDING 状态。如果出现错误,返回一个负数。具体可参看在Iom.h中的定义。 这个函数只有在驱动程序初装载和初始化之后。其中的句柄参数是由FVID_create()正确执行后产生的。 /* allocate a buffer from the device */ status = FVID_alloc(chanHandle, dispBuf); 应用程序送一个控制命令到mini-driver status = FVID_control (fvidChan, cmd, args); FVID_Handle fvidChan /* 设备实体的句柄 */ Int cmd /* 控制命令 */ Ptr args /* 指向命令参数的指针 */ Int status /* 如果成功返回IOM_COMPLETED */ 应用程序调用FVID_control将视频编解码器的控制参数传给mini-driver。 fvidChan参数是视频驱动程序的一个通路句柄。是在调用FVID_create时产生的。 cmd参数是指定的控制命令。 args参数是指向与控制命令相关联的传给驱动程序的参数结构的指针。 FVID_control调用成功后返回IOM_COMPLETED。如果出现错误,返回一个负数。具体可参看在Iom.h中的定义。 这个函数只有在驱动程序初装载和初始化之后。其中的句柄参数是由FVID_create()正确执行后产生的。 /* abort all pending video driver I/O jobs */ FVID_control(fvidChan, IOM_ABORT, NULL); FVID_create Syntax Parameters Return Value Description Constraints Example FVID_delete Syntax Parameters Return Value Description 应用程序产生一个FVID实体对象 fvidChan = FVID_create (name, mode, *status, optArgs, *attrs); String name /* 设备实例的参数字符串 */ Int mode /* 产生设备实体的接口类型*/ Int *status /* 返回状态 */ Ptr optArgs /* 可选参数*/ FVID_Attrs *attrs /* */ FVID_Handle fvidChan /* 设备实例的句柄 */ 应用程序调用FVID_create产生并初始化一个视频驱动的通路实例。 name参数是当设备在配置文件中或是程序运行中被创建时所指定的设备名称。 mode参数指出设备以何种方式打开,在此mode既可以是IOM_INPUT(用于视频采集),也可以是IOM_OUTPUT(用于视频显示)。 status参数是输出参数,本函数用此指针来填充由mini-driver返回的状态信息。 attrs参数是指向FVID_Attrs结构的指针: typedef struct FVID_Attrs { Uns timeout; } FVID_Attrs; 其中timeout成员是由类驱动产生的同步体的同步时间。如果其值为SYS_FOREVER将使FVID_alloc, FVID_free 与FVID_exchange 调用同步不确定的时间,直至驱动程序处理完调用。若是其它的值,则这些API只阻塞指定的时间。其单位为系统时间。如果timeout指定为0,则这些API不进行阻塞,直接从驱动程序返回。这种情况下应用程序需要检查返回的状态是否是正确。如果果timeout指定为非0值,需要注意FVID_alloc, FVID_free 与FVID_exchange只能被使用在DSP/BIOS的任务中。 FVID_create如果成功调用则返回句柄。这个句柄是被FVID模块的其它调用使用的,如果返回NULL,则为打开失败 这个函数只有在驱动程序初装载和初始化之后。 /* Initialize the attributes */ FVID_ATTRS dispAttrs = FVID_ATTRS; /* Create an instance to a video display device */ chan- Handle = FVID_create(“\\display0”, IOM_INPUT, NULL, NULL, &dispAttrs); 应用程序删除一个FVID实体对象 status = FVID_delete (fvidChan); FVID_Handle fvidChan /*设备实体的句柄 */ Int status /*如果成功返回IOM_COMPLETED */ 应用程序调用FVID_delete关闭一个驱动程序的通路实体. fvidChan参数是视频驱动程序的一个通路句柄。在调用FVID_create 时产生的。 FVID_delete调用成功后返回IOM_COMPLETED。如果出现错误,返回一个负数。具体可参看在Iom.h中的定义。 Constraints 这个函数只有在驱动程序初装载和初始化之后。其中的句柄参数是由 FVID_create()正确执行后产生的。 Example /* allocate a buffer from the device */ status = FVID_delete(chanHandle); FVID_exchange 应用程序与驱动程序交换数据缓冲区 Syntax Parameters Return Value Description Constraints Example FVID_free Syntax Parameters Return Value Description status = FVID_exchange (fvidChan, bufp); FVID_Handle fvidChan /*设备实体的句柄 */ Ptr bufp /*指向要交换的缓冲区的指针*/ Int status /*如果成功返回IOM_COMPLETED */ 当应用程序调用FVID_exchange即采集与显示驱动程序将其准备好 的一个数据缓冲区交给应用程序,同时应用程序将其处理过的缓冲区还给采集与显示驱动程序。调用FVID_exchange与顺序调用FVID_free与FVID_alloc效果相同。只是它可以同时完成这两步操作。在使用这个API之间,应首先调用FVID_alloc使应用程序从驱动中获取一个有效的缓冲区。这个API的调用导致在mini-driver中调用mdSubmit。 fvidChan参数是视频驱动程序的一个通路句柄。是调用FVID_create时产生的。 Bufp参数是指向由应用程序拥有的,准备还给驱动程序缓冲区的指针。这个指针参数即是输入也为输出参数。当调用成功返回时,Bufp保存了从驱动程序交换回的缓冲区的指针。 FVID_exchange调用成功后返回IOM_COMPLETED。如果请求被mini-driver排入队列,将返回IOM_PENDING 状态。如果出现错误,返回一个负数。具体可参看在Iom.h中的定义。 这个函数只有在驱动程序初装载和初始化之后。其中的句柄参数是由 FVID_create()正确执行后产生的。 /* allocate a buffer from the device */ status = FVID_exchange(chanHandle, dispBuf); 应用程序归还驱动程序数据缓冲区 status = FVID_free (fvidChan, bufp); FVID_Handle fvidChan /*设备实体的句柄 */ Ptr bufp /*指向要归还的缓冲区的指针*/ Int status /*如果成功返回IOM_COMPLETED */ 应用程序调用FVID_free可以将其拥用的已处理过的缓冲区归还给视频采集与显示驱动。这个API函数调用在mini-driver中的映射为mdSubmit函数。 fvidChan参数是视频驱动程序的一个通路句柄。是调用FVID_create时产生的。 Bufp参数是指向FVID_Frame 结构的指针。是由驱动程序管理,但还未交还给驱动程序的缓冲区。 Constraints FVID_alloc调用成功后返回IOM_COMPLETED。如果请求被mini-driver排入队列,将返回IOM_PENDING 状态。如果出现错误,返回一个负数。具体可参看在Iom.h中的定义。 这个函数只有在驱动程序初装载和初始化之后。其中的句柄参数是由FVID_create()正确执行后产生的。需要指出的是,归还的一定是应用程序调用FVID_alloc或FVID_exchange获取的FVID_Frame 类型的指针。 /* free a buffer back to the device */ status = FVID_free(chanHandle, dispBuf); Example 因篇幅问题不能全部显示,请点此查看更多更全内容