绘制多个图形

来源:互联网 发布:怎么做好一个淘宝客 编辑:程序博客网 时间:2024/05/20 10:11

         当TW8835需要绘制一个或者多个图像时,由于TW8835需要操作OSD SPI窗口寄存器,这些操作往往都是调用函数进行的。然而,TW8835在Vertical Blank调用的函数个数是有限的,因此有的函数会在非Vertical Blank时刻调用,这样就导致了同一个函数在Vertical Blank和非Vertical Blank时刻执行的时间不同(如图一所示),因此,绘图函数的可控性变差。

图一

         为了解决这个问题,TW8835采用shadowregister(影子寄存器)的原理。首先将TW8835各个窗口的配置参数存放在影子寄存器中,等所有窗口都配置完了以后,然后在等到Vertical Blank时刻执行将影子寄存器中的值按照对应关系一次拷贝到HW(HardWare)Register(硬件寄存器)中,这样就能够保证所有窗口的配置在同一个Vertical Blank时期执行完毕。

         然而,TW8835并没有为WindowBuffer配置了硬件的影子寄存器。但是,我们可以采用影子寄存器原理,在RAM中申请这样一段空间,作为影子寄存器使用。我们把配置数据先分别写入申请的RAM空间中,然后等待Vertical 时刻一次将RAM中的数据拷贝到硬件寄存器中。

         查看TW8835的datasheet可知,TW8835 OSD窗口总共有4个,其中Win0可以用于动态图像,并且其优先级可以进行设置,Win1优先级最低,一般用于背景图像显示,Win8优先级最高。每个窗口寄存器的起始地址如表一所示:

表一

WIN0

WIN1

WIN2

WIN3

WIN4

WIN5

WIN6

WIN7

WIN8

0x420

0x440

0x450

0x460

0x470

0x480

0x490

0x4A0

0x4B0

其中WIN0占有20h个地址空间,其余WIN都只占有10h个地址空间。因此,我们可以在RAM中申请10*0x10个连续BYTE空间作为假的影子寄存器。如,data OsdWinBuff[10*0x10]

OSDWinBuff的机构规划如表二所示:

16

16

16

16

16

16

16

16

16

16

WIN0

WIN1

WIN2

WIN3

WIN4

WIN5

WIN6

WIN7

WIN8

如今,我们已经设置好了影子寄存器,现在我们需要考虑的问题是:第一,如何清除OsdWinBuff;第二:如何将OsdWinBuff的值拷贝到HW Register中。

下面,我们来解决第一个问题,如何,清除OsdWinBuff,这个问题我们可以采用简单的办法,比如直接采用一个for循环,即可以对OsdWinBuff的每个元素进行清除。但是这样我们就没有考虑到我们各个窗口的结构。因此我们采用第二种方法,虽然,我们只有9个窗口,但是我们把Win0假设分为2个,即每个窗口都是16字节,因此我们可以采用嵌套的for循环进行赋值,如下所示:

         for(i=0;i<10; i++)

         {

                   for(j=0;j<0x10;j++)

                            OsdWinBuff[i*0x10+j]= 0;

}

第二个问题:我们如何将OsdWinBuff中的数据拷贝到HWRegister中

         首先,我们从上面表一就可以看出每个窗口之间存在一定的共性,即窗口起始地址都是0x10的倍数,处理Win0占用32字节空间,其余窗口都是占用16字节空间。因此,数据拷贝函数采用传递两个参数,即起始WIN(start),结束WIN(end),他们范围都是0到8。

         因为,WIN0存在一定特性,所以对待WIN0就需要特别对待。当start>0时,则需要考虑WIN0占用32字节,因此start需要加1,end是同样的原理。

void SOsdWinBuffWrite2Hw(BYTE start, BYTEend)

{

         DATABYTE i;

         DATABYTE reg_i;

         DATABYTE XDATA *data_p;

 

         if(start) start++;          //窗口0占32个字节

         if(end) end++;

 

         WriteTW88Page(PAGE4_SOSD);

         data_p= &SpiWinBuff[start<<4];

         for(i=start; i<=end; i++)

         {

                   reg_i= (i<<4)+0x20;

                   WriteTW88(reg_i++,*data_p++);  //0

                   WriteTW88(reg_i++,*data_p++);  //1

                   WriteTW88(reg_i++,*data_p++);  //2

                   WriteTW88(reg_i++,*data_p++);  //3

                   WriteTW88(reg_i++,*data_p++);  //4

                   WriteTW88(reg_i++,*data_p++);  //5

                   WriteTW88(reg_i++,*data_p++);  //6

                   WriteTW88(reg_i++,*data_p++);  //7

                   WriteTW88(reg_i++,*data_p++);  //8

                   WriteTW88(reg_i++,*data_p++);  //9

                   WriteTW88(reg_i++,*data_p++);  //A

                   WriteTW88(reg_i++,*data_p++);  //B

                   WriteTW88(reg_i++,*data_p++);  //C

                   WriteTW88(reg_i++,*data_p++);  //D

                   WriteTW88(reg_i++,*data_p++);  //E

                   if(i)

                   {

                            data_p++;                                               //跳过F

                   }

                   else

                   {

                            WriteTW88(reg_i++,*data_p++); //F                 

                            i++;                                               //处理WIN0后半部分

                            WriteTW88(reg_i++,*data_p++); //10

                            WriteTW88(reg_i++,*data_p++); //11

                            WriteTW88(reg_i++,*data_p++); //12

                            WriteTW88(reg_i++,*data_p++); //13

                            WriteTW88(reg_i++,*data_p++); //14

                            WriteTW88(reg_i++,*data_p++); //15

                            WriteTW88(reg_i++,*data_p++); //16

                            reg_i+= 9;                                       //移动剩余的

                            data_p+= 9;                                    //跳过没使用数据

                   }

         }

}