摘要:介绍用C8051F015微控制器控制硬盘进行HDTV码流存取的高清码流回放机的硬件设计和软件编程。该系统作为解码器的前端,可以实现HDTV 码流的适时回放。 关键词:HDTV 码流 ATA/ATAPI-4标准 LBA模式 CPLD 随着HDTV在全球的兴起以及数字技术的日趋成熟,音/视频产品数字化、高清晰度化已成为未来家电视听产品的大趋势。高清晰度电视HDTV(High- Definition Television)采用了国际上流行的MPEG-2标准,MPEG-2规定了数字图像的音视频编解码算法以及传送的码流应该符合的语法和语义,而其编解码算法又参考了听觉心理模型和视觉心理模型。HDTV的图像格式为1920%26;#215;1080I,传输码率高达20Mbps,同时采用的视频压缩技术可使HDTV的每一帧包含更多的信息,大大提高图像的清晰度。HDTV在音频压缩方面采用了数字音频的编码和压缩技术,现有的数字音频编码压缩方案有MPEG、Dolby AC-3和美国AT%26;amp;T的MPAC以及欧洲的MIX。它们都能实现5.1声道,其声道数可以扩展到5.1,即三个前面的声道(L、C、右声道R)、两个环绕声道(左环绕声道Ls、右环绕声道Rs)和一个低音效果声道LFE,使声音效果可以达到家庭影院的音响效果。HDTV声光效果上优势,注定它的发展有着技术和市场的双重必然性。为了配合HDTV及相关技术产品的推广,笔者开发了一个既可以作为MPEG解码器信号源,又可以作为信道编码/调制器信号源的码流回放机,应用于数字电视产品的开发、生产调试及展示宣传。 HDTV节目有传输码率高、节目信息最大的特点。为了研制出符合大容量高速率要求的码流回放机,传统的方法是用操作系统控制硬盘的读写操作。这样做的好处在于:首先,PC机的主频很高,用来作为控制码流的时钟信号在速度上不会有瓶颈问题;其次,对硬盘里HDTV节目的读取是基于文件系统的,研发人员不用写硬盘的驱动程序,软件的工作量大大减小。但是,就码流回放机本身而言,它是一个单任务设备,采用操作系统的方案无疑将造成CPU资源的极大浪费。因此,笔者设想用单片机或DSP控制硬盘的读写操作。只要所选微控制器上速度上满足高清晰度电视的码率要求,在技术上就能够实现预期的功能。与操作系统方案相比较,用微控制器无疑可以大大降低生产成本,同时也降低了硬件设计的难度。不过,在这种方式下,需要编写硬盘的底层驱动程序。 图1 C8051F015内部结构 1 总体方案 华天HTTS HDTV第III代码流回放机可以播放数字高清晰度电视HDTV码流。该码泫回放机整体设计没有采用在工控机上研发PCI卡驱动硬盘的方案,而是遵照AT Attachment with Packet Interface Extension(ATA/ATAPI-4)标准,用8位单片机C8051F015通过PIO方式按照LBA模式直接对硬盘进行物理级的读写操作。硬盘接收微控制器的命令后按照逻辑地址顺序输出HDTV码流给两片FIFO,硬盘输出的16位数据通过两片8位FIFO缓存后输出给CPLD进行拆分以识别包同步和字节同步。经CPLD解析后的数据流再经过解码器解码及适当后处理,送显示器、扬声器以提供视频、音频信号。既可以作为MPEG解码器的信号源,又可以作为信道编码/调制器的信号源。 2 C8051F015内部结构 C8051F015的内部结构如图1所示。它使用了CYGNAL的专利——CIP-51微控制器内核CIP-51。CIP-51与MCS-51的指令集完全兼容,可以使用标准803x/805x的汇编器和编译器进行软件开发。同时,CIP-51采用流水线结构,70%的指令执行时间为1或2个系统时钟周期,外部晶振最大可以到25MHz。8位HDTV输出码流的标准时钟频率为19MHz和25MHz。考虑到硬盘的输出是16位,理论上采用这款MCU完全可以达到速度要求。这里,就系统的初始化问题有几点说明:(1)内外部晶振切换。在外部晶体振荡器被允许时,系统晶体驱动器的输出端XTAL2脚会出现一个瞬时脉冲,该脉冲足以在晶体实际启动前,将OSCXCN寄存器中的XTLVLD位置1。在允许晶体振荡器和检查XTLVLD位之间引入1ms的延时,可以防止提前切换到外部晶振。(2)配置交叉开关。系统内部交叉开关根据优先权译码表将所选择的内部数字资源分配到I/O引脚,寄存器XBR0、XBR1、 XBR2用于选择内部数字功能或让I/O引脚默认为I/O端口。I/O引脚的输出驱动器特性用端口配置寄存器PRT0CF、PRT1CF、PRT2CF和 PRT3CF定义。每个端口输出驱动器都可被配置为漏极开路或推挽方式。将配置寄存器的相应位配置为漏极开路,并在外部加1kΩ的上拉电阻,可用3.3V 供电的C8051F015去驱动5V供电的硬盘。初始化程序: void sysclk_init(void) {WDTCH=0xde; //禁止看门狗定时器 WDTCN=0xad; //启动外部振荡器 OSCXCN=0x67; //外接24MHz的晶振 //配置外部晶体 while((OSCXCN%26;amp;XTLVLD_BIT= =0) {} OSCICN=0x88; //选择外部振荡器作为系统时钟,禁止内部振荡 } //配置交叉开关 void xbar_init(void) {XBR0=0x04; //RX TX连到两个引脚 XBR1=0x04; //INT0连到断口引脚 XBR2=0x40; //使能交叉开关和弱上拉 PRT0CF=0xff; //控制FIFO读写,使能 PRT1CF=0x07; //控制CPLD读写,使能 PRT2CF=0x00; (P0口的所有输出为弱上拉(写硬盘命令字) PRT3CF=0x00; //控制硬盘读写,使能 }
3 ATA/ATAPI-4标准下的硬盘内部寄存器和PIO读时序关系 3.1 硬盘内部寄存器 目前,大部分计算机配置了两个IDE接口,地址范围分别为:0170~0117,0376~0376(对应PC机的Secondary IDE Channel)和01F0~01F6,03F6~03F6(对应PC机的Primary IDE Channel)。地址译码如表1所示。 表1 地址译码 CS1FX CS3FX DA2 DA1 DA0 Address 1 0 0 0 0 170 1 0 0 0 1 171 1 0 0 1 0 172 1 0 0 1 1 173 1 0 1 0 0 174 1 0 1 0 1 175 1 0 1 1 0 176 1 0 1 1 1 177 0 1 1 1 0 376 0 1 1 1 1 377 0 1 * * * 未用 %26;#183;数据寄存器(170R/W):这是一个16位PIO数据寄存器,用于对扇区的读、写和格式化操作。MCU通过该寄存器向硬盘控制寄存器写入或从硬盘控制器读出扇区缓冲区的数据。 %26;#183;错误寄存器(171R):该寄存器是一个8位的寄存器,它反映控制寄存器在诊断方式或操作方式下的错误原因。 %26;#183;扇区数寄存器(172R/W):它记录读、写命令的扇区数。当多扇区传输时,每完成一个扇区操作,该寄存器自动减1,直至为0。如果初值为0,则表示256;如果有错误生,该寄存器包含已经操作成功的扇区数。 %26;#183;扇区号寄存器(173R/W):它记录读、写和校验命令指令起始扇区号。本文用LBA模式。该寄存器记录逻辑扇区的0字节。 %26;#183;柱面号寄存器(174 175 R/W):它记录读、写、校验、寻址和格式化命令指定的柱面号,在LBA寻址方式下,这2个寄存器包含起始扇区的1和2字节。 %26;#183;驱动器/磁头寄存器(176R/W):它记录读、写、校验、寻道和格式化命令指定的驱动器号、磁头号和寻址方式。在ATA /ATAPI-4中其定义如表2所示。 表2 驱动器/磁头寄存器在ATA/ATAPI-4中的定义 D7 D6 D5 D4 D3 D2 D1 D0 1 L 1 DEV HS3 HS2 HS1 HS0 HS0~HS3(磁头选择):在LBA方式中,是逻辑扇区的高4位。 DEV驱动器选择:0选择主驱动器,1选择从驱动器。 L(LBA方式):L=1,置驱动器为LBA模式;L=0,置驱动器为CHS模式。 %26;#183;状态寄存器(177 R);反映了硬盘执行命令后的状态。读该寄存器清除中断请求信号,为避免清除中断,可以读辅助状态寄存器376h。这两个寄存器的内容完全一样。在 ATA/ATAPI-4中其定义如表3所示。 BSY:驱动器忙。 DRDY:驱动器准备好。 DRQ:请求服务,驱动器请求通过寄存器与处理器交换一个字节数据。 ERR:命令执行错误。 3.2 硬盘PIO方式下特定区域多扇区读的操作 如果想从硬盘的特定扇区读出码流信息,首先主机(C8051F015)要对驱动器/磁头寄存器、柱面号寄存器、扇区号寄存器、扇区数寄存器设置参数。完毕后要等待至少400ns才能去读状态寄存器的参数判断以上设置是否有效。硬盘接收命令后置BSY=1,并开始执行命令。硬盘如果准备好传送数据包,就置 DRQ=1,同时清零BSY。当机循环读状态寄存器或辅助状态寄存器判断BSY=0%26;amp;DRQ=1,一旦硬盘状态符合要求,主机写参数 0x80(128扇区)到数据寄存器(0x170),并写0x20(PIO读)到命令寄存器(0x177),表示要求读出硬盘相应地址里的数据块。硬盘判断数据寄存器被置数后立即置BSY=1%26;amp;DRQ=0。主机读到置位信息后给硬盘读时钟,硬盘输出数据直到数据包传完为止。 表3 状态寄存器在ATA/ATAPI-4中的定义 D7 D6 D5 D4 D3 D2 D1 D0 BSY DRDY # # DRQ obsolete obsolete ERR 4 系统设计方案 4.1 系统硬件构成 基于8位微控制器的系统设计方案如图2所示。主系统中以C8051F015为控制核心,C8051F015产生硬盘和FIFO的读写时序(为了避免硬盘寄存器参数也被写入FIFO,在硬件上要把二者的读写时钟分开。);硬盘输出的16位数据分离低8位分别送入两片64KB的FIFO缓存。数据经缓存后持续地输出到CPLD,CPLD对16位数据流进行拆分,同时识别包同步和字节同步。这样,原始的一路HDTV码流就被分成3路输送给解码器解码。主系统通过串行总线与前面板相连,采用通用单片机AT89C51为前面板的控制核心。AT89C51接收来自键盘的命令并在LCD上以文字和图形的方式展现在用户面前,同时通过串口通信,启动主控制器执行命令。 4.2 系统软件设计 4.2.1 存码流部分 本系统没有引入操作系统和文件格式,所以码流文件存入硬盘时就不能按文件格式,而只能按二进制流的方式从PC机的码流文件中读出数据,再按同样的方式写入裸盘。为了解决码流的总是,试图调用BIOS中断,让BIOS的硬盘服务流程负责把INT13的读写请求转化为ATA界面对硬盘的请求,并执行数据I/O 传输的物理动作。但由于BIOS本身寄存器的限制,用它去访问硬盘有8.4G容限的问题。如果想突破这个限制而用扩展的INT13,将是一个比较复杂的过程。可以利用PC机上的Secondary IDE Channel(0x170~0x177)作为硬盘寄存器的端口地址。在这个硬件平台下,可以直接将fread()函数读出的码流按块写入目标硬盘,甚至不要求大多地考虑时序问题。 4.2.2 读码流部分 这部分软件是在上述硬件系统平台上直接编程。系统在启动硬盘前要等待串行中断,接收由前面板发出的命令,再根据接收的数据信息具体决定应该播放哪几个节目;随后对硬盘、FIFO进行初始化,启动CPLD,FIFO输出数据时钟信号,并让硬盘按命令输出数据流。数据在总线稳定的时间内给FIFO写时钟,以采集正确的码流信息(这里强调时序)。FIFO有“半满”(HF)标志,用HF去触发中断,有中断请求,就让硬盘输出64KB的数据。如此循环,保证 FIFO不空。当FIFO输出第一个数据时,CPLD开始对数据流进行拆分,并按照HDTV码流的格式标准对数据流进行判别(HDTV码流188字节为一个包,每个包头是0x47),即每计数1次,就输出一个比特同步,每计数188次并识别下一个数为0x47,就输出一个包同步。这部分程序流程如图3。 IP
4.2.3 应用程序 系统设置硬盘寄存器参数时,首先调用SetMode()函数设定硬盘的IDLE状态和自掉电功能,可以保证硬盘在不工作的情况下,磁头会复位到“登陆区”;然后调用SetAdress()函数选择对应的寄存器;接下来可以调用ReadSector()函数进行多扇区读操作。以下是寄存器选择子函数和多扇区读子函数。 //寄存器选择子函数; void SetAddress(unsigned char cs,unsigned char adr){ DA0=((adr %26;amp; 0x01)= =0x01; DA1=((adr %26;amp; 0x02) = =0x02); DA2=((adr %26;amp; 0x04) = =0x04); if(cs= =CTRL) { nCS1FX=1; nCS3FX=0; }else { nCS1FX=0; nCS3FX=1; } } //多扇区读子函数: unsigned char ReadSector(unsigned long point,unsigned char *Buffer){ unsigned int i,k; WriteBYTE(CMD,6,0xe0); //LBA模式 WriteBYTE(CMD,5,point>>16); //LBA模式下的高16位地址 WriteBYTE(CMD,4,point>>8); //LBA模式下的高8位地址 WriteBYTE(CMD,3,point); //LBA模式下的低8位地址 WriteBYTE(CMD,2,0x80); //一次读写的扇区数 //Issue read sector command... WriteBYTE(CMD,7,0x20); //0x20多为扇区读命令 Timer 10mSec=10000; while((ReadBYTE(CMD,7)%26;amp;0x08)!=0x08 %26;amp;%26;amp; Timer 10mSec); //等待DRQ=1或者timeout if(Timer 10mSec= =0)return 0xFF; //Fetch the sector... LSBDATA=ALLINPUT; //Select address and activate CS SetAddress(CMD,0); for(k=0;k<0x80;k++) for(i=0;i<512;i+=2){ //一次读两字节 nDIOR=0; //硬盘的读时钟 WCK=1; WCK=0; nDIOR=1; } nCS1FX=1; //复位CS nCS3FX=1; return ReadBYTE(CMD,1); //返回错误寄存器的信息 } 本文是“第三代码流回放机研制”课题的一个重要组成部分。本方案利用微控制器对硬盘进行基于LBA模式下的读写操作(不用操作系统),硬软件简洁可靠,技术上也解决前期产品的两个难题: (1)一些旧机器的BIOS不支持INT 13h Extension,无法访问8.4G以上硬盘空间; (2)WINDOWS操作系统不支持存储1.2G以上码流文件。 将此系统逆向设计,能够研发出适时录制TS流和卫星节目的仪器。