ARM2440 LCD实验

 

1. S3C2440内部LCD控制器结构图:

我们根据数据手册来描述一下这个集成在S3C2440内部的LCD控制器:

a:LCD控制器由REGBANK、LCDCDMA、TIMEGEN、VIDPRCS寄存器组成;

b:REGBANK由17个可编程的寄存器组和一块256*16的调色板内存组成,它们用来配置LCD控制器的;

c:LCDCDMA是一个专用的DMA,它能自动地把在侦内存中的视频数据传送到LCD驱动器,通过使用这个DMA通道,视频数据在不需要CPU的干预的情况下显示在LCD屏上;

d:VIDPRCS接收来自LCDCDMA的数据,将数据转换为合适的数据格式,比如说4/8位单扫,4位双扫显示模式,然后通过数据端口VD[23:0]传送视频数据到LCD驱动器;

e:TIMEGEN由可编程的逻辑组成,他生成LCD驱动器需要的控制信号,比如VSYNC、HSYNC、VCLK和LEND等,而这些控制信号又与REGBANK寄存器组中的LCDCON1/2/3/4/5的配置密切相关,通过不同的配置,TIMEGEN就能产生这些信号的不同形态,从而支持不同的LCD驱动器(即不同的STN/TFT屏)。

  FIFO存储器位于LCDCDMA.。当FIFO空或部分空时,LCDCDMA要求从帧缓冲中取来要显示的图像数据,而这个帧缓冲是LCD控制器在RAM中开辟的一片缓冲区。当这个传输请求被存储控制器中的总线仲裁器接收到后,从系统存储器到内部FIFO就会成功传输4个字节。FIFO的总大小是28个字,其中低位FIFOL是12个字,高位FIFOH是16个字。

 

2. 常见TFT屏工作时序分析:

 

3.LCD提供的外部接口信号:
VSYNC/VFRAME/STV:垂直同步信号(TFT)/帧同步信号(STN)/SEC TFT信号;
HSYNC/VLINE/CPV:水平同步信号(TFT)/行同步脉冲信号(STN)/SEC TFT信号;
VCLK/LCD_HCLK:象素时钟信号(TFT/STN)/SEC TFT信号;
VD[23:0]:LCD像素数据输出端口(TFT/STN/SEC TFT);
VDEN/VM/TP:数据使能信号(TFT)/LCD驱动交流偏置信号(STN)/SEC TFT 信号;
LEND/STH:行结束信号(TFT)/SEC TFT信号;
LCD_LPCOE:SEC TFT OE信号;
LCD_LPCREV:SEC TFT REV信号;
LCD_LPCREVB:SEC TFT REVB信号。

 

所有显示器显示图像的原理都是从上到下,从左到右的。这是什么意思呢?这么说吧,一副图像可以看做是一个矩形,由很多排列整齐的点一行一行组成,这些点称之为像素。那么这幅图在LCD上的显示原理就是:
A:显示指针从矩形左上角的第一行第一个点开始,一个点一个点的在LCD上显示,在上面的时序图上用时间线表示就为VCLK,我们称之为像素时钟信号;
B:当显示指针一直显示到矩形的右边就结束这一行,那么这一行的动作在上面的时序图中就称之为1 Line;
C:接下来显示指针又回到矩形的左边从第二行开始显示,注意,显示指针在从第一行的右边回到第二行的左边是需要一定的时间的,我们称之为行切换;
D:如此类推,显示指针就这样一行一行的显示至矩形的右下角才把一副图显示完成。因此,这一行一行的显示在时间线上看,就是时序图上的HSYNC;
E:然 而,LCD的显示并不是对一副图像快速的显示一下,为了持续和稳定的在LCD上显示,就需要切换到另一幅图上(另一幅图可以和上一副图一样或者不一样,目 的只是为了将图像持续的显示在LCD上)。那么这一副一副的图像就称之为帧,在时序图上就表示为1 Frame,因此从时序图上可以看出1 Line只是1 Frame中的一行;
F:同样的,在帧与帧切换之间也是需要一定的时间的,我们称之为帧切换,那么LCD整个显示的过程在时间线上看,就可表示为时序图上的VSYNC。

 

上面时序图上各时钟延时参数的含义如下:(这些参数的值,LCD产生厂商会提供相应的数据手册)
VBPD(vertical back porch):表示在一帧图像开始时,垂直同步信号以后的无效的行数,对应驱动中的upper_margin;
VFBD(vertical front porch):表示在一帧图像结束后,垂直同步信号以前的无效的行数,对应驱动中的lower_margin;
VSPW(vertical sync pulse width):表示垂直同步脉冲的宽度,用行数计算,对应驱动中的vsync_len;
HBPD(horizontal back porch):表示从水平同步信号开始到一行的有效数据开始之间的VCLK的个数,对应驱动中的left_margin;
HFPD(horizontal front porth):表示一行的有效数据结束到下一个水平同步信号开始之间的VCLK的个数,对应驱动中的right_margin;
HSPW(horizontal sync pulse width):表示水平同步信号的宽度,用VCLK计算,对应驱动中的hsync_len;

对于一个已知尺寸的LCD屏,只要确定了VCLK值,行频和场频就应该知道了。但这样还不行的,因为在每一帧时钟信号中,还会有一些与屏显示无关的时钟出现,这就给确定行频和场频带来了一定的复杂性。如在HSYNC信号先后会有水平同步信号前肩(HFPD)和水平同步信号后肩(HBPD)出现,在VSYNC信号先后会有垂直同步信号前肩(VFPD)和垂直同步信号后肩(VBPD)出现,在这些信号时序内,不会有有效像素信号出现,另外HSYNC和VSYNC信号有效时,其电平要保持一定的时间,它们分别叫做水平同步信号脉宽HSPW和垂直同步信号脉宽VSPW,这段时间也不能有像素信号。因此计算行频和场频时,一定要包括这些信号。

 

对于以上这些参数的值将分别保存到REGBANK寄存器组中的LCDCON1/2/3/4/5寄存器中:(对寄存器的操作请查看S3c2440数据手册LCD部分)

 

 

 

4. 帧缓冲(FrameBuffer):
  帧缓冲是Linux为显示设备提供的一个接口,它把一些显示设备描述成一个缓冲区,允许应用程序通过 FrameBuffer定义好的接口访问这些图形设备,从而不用去关心具体的硬件细节。对于帧缓冲设备而言,只要在显示缓冲区与显示点对应的区域写入颜色值,对应的颜色就会自动的在屏幕上显示。下面来看一下在不同色位模式下缓冲区与显示点的对应关系:

 

一.初始化(GPC管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND)

二.对于控制TFT LCD来说,只用设置寄存器LCDCON1~LCDCON5(用于选择LCD类型,设置各类控制信号的时间特性等)和LCDSADDR1~LCDSADDR3(用于设置帧内存地址)几个寄存器就可以了。对于这几个寄存器的设置

其中VBPD,VFPD,VSPW,HBPD,HFPD,HSPW这几个参数是有LCD生产商提供的,根据其datashet修改就是了。

8位色显比16位等多初始化了调色板

  1 /*
  2  * FILE: lcddrv.h
  3  * 操作LCD控制器、调色板等的底层函数接口
  4  */
  5 
  6 #ifndef __LCDDRV_H__
  7 #define __LCDDRV_H__
  8 
  9 #include <types.h>
 10 
 11 #define LOWER21BITS(n)  ((n) & 0x1fffff)
 12 
 13 #define BPPMODE_1BPP    0x8
 14 #define BPPMODE_2BPP    0x9
 15 #define BPPMODE_4BPP    0xA
 16 #define BPPMODE_8BPP    0xB
 17 #define BPPMODE_16BPP   0xC
 18 #define BPPMODE_24BPP   0xD
 19 
 20 #define LCDTYPE_TFT     0x3
 21 
 22 #define ENVID_DISABLE   0
 23 #define ENVID_ENABLE    1
 24 
 25 #define FORMAT8BPP_5551 0
 26 #define FORMAT8BPP_565  1
 27 
 28 #define HSYNC_NORM      0
 29 #define HSYNC_INV       1
 30 
 31 #define VSYNC_NORM      0
 32 #define VSYNC_INV       1
 33 
 34 #define BSWP            1
 35 #define HWSWP           1
 36 
 37 //TFT LCD Panel(240*320)
 38 #define MODE_TFT_1BIT_240320     (0x4101)
 39 #define MODE_TFT_8BIT_240320      (0x4102)
 40 #define MODE_TFT_16BIT_240320    (0x4104)
 41 #define MODE_TFT_24BIT_240320    (0x4108)
 42 
 43 //TFT 240320
 44 #define LCD_XSIZE_TFT_240320     (240)    
 45 #define LCD_YSIZE_TFT_240320     (320)
 46 
 47 //TFT 240320
 48 #define HOZVAL_TFT_240320    (LCD_XSIZE_TFT_240320-1)
 49 #define LINEVAL_TFT_240320    (LCD_YSIZE_TFT_240320-1)
 50 
 51 #define CLKVAL_TFT_240320    (4)
 52 // 60hz @133Mhz
 53 // (9) 60hz @100Mhz
 54 
 55 //Timing parameter for LTS350Q1(SAMSUNG) 
 56 #define VBPD_240320        ((6-1)&0xff)
 57 #define VFPD_240320        ((4-1)&0xff)
 58 #define VSPW_240320        ((2-1) &0x3f)
 59 #define HBPD_240320        ((11-1)&0x7f)
 60 #define HFPD_240320        ((2-1)&0xff)
 61 #define HSPW_240320        ((1-1)&0xff)
 62 
 63 
 64 
 65 //TFT LCD Panel(640*480)
 66 #define MODE_TFT_1BIT_640480     (0x4201)
 67 #define MODE_TFT_8BIT_640480     (0x4202)
 68 #define MODE_TFT_16BIT_640480    (0x4204)
 69 #define MODE_TFT_24BIT_640480    (0x4208)
 70 
 71 //TFT 640480
 72 #define LCD_XSIZE_TFT_640480     (640)    
 73 #define LCD_YSIZE_TFT_640480     (480)
 74 
 75 //TFT640480
 76 #define HOZVAL_TFT_640480    (LCD_XSIZE_TFT_640480-1)
 77 #define LINEVAL_TFT_640480    (LCD_YSIZE_TFT_640480-1)
 78 
 79 //Timing parameter for V16C6448AB(PRIME VIEW) 
 80 #define VBPD_640480        ((33-1)&0xff)
 81 #define VFPD_640480        ((10-1)&0xff)
 82 #define VSPW_640480        ((2-1) &0x3f)
 83 #define HBPD_640480        ((48-1)&0x7f)
 84 #define HFPD_640480        ((16-1)&0xff)
 85 #define HSPW_640480        ((96-1)&0xff)
 86 
 87 
 88 #define CLKVAL_TFT_640480     (1)
 89     //53.5hz @90Mhz
 90     //VSYNC,HSYNC should be inverted
 91     //HBPD=47VCLK,HFPD=15VCLK,HSPW=95VCLK
 92     //VBPD=32HSYNC,VFPD=9HSYNC,VSPW=1HSYNC
 93 
 94 #define LCDFRAMEBUFFER 0x30400000
 95 
 96 /*
 97  * 初始化用于LCD的引脚
 98  */
 99 void Lcd_Port_Init(void);
100 
101 /*
102  * 初始化LCD控制器
103  * 输入参数:
104  * type: 显示模式
105  *      MODE_TFT_8BIT_640480  : 640*640 8bpp的TFT LCD
106  *      MODE_TFT_16BIT_640480 : 640*640 16bpp的TFT LCD
107  */
108 void Tft_Lcd_Init(int type);
109 
110 /*
111  * 设置调色板
112  */
113 void Lcd_Palette8Bit_Init(void);
114 
115 /*
116  * 设置LCD控制器是否输出信号
117  * 输入参数:
118  * onoff: 
119  *      0 : 关闭
120  *      1 : 打开
121  */
122 void Lcd_EnvidOnOff(int onoff);
123 
124 /*
125  * 设置是否输出LCD电源开关信号LCD_PWREN
126  * 输入参数:
127  *     invpwren: 0 - LCD_PWREN有效时为正常极性
128  *               1 - LCD_PWREN有效时为反转极性
129  *     pwren:    0 - LCD_PWREN输出有效
130  *               1 - LCD_PWREN输出无效
131  */
132 void Lcd_PowerEnable(int invpwren, int pwren);
133 
134 /*
135  * 使用临时调色板寄存器输出单色图像
136  * 输入参数:
137  *     color: 颜色值,格式为0xRRGGBB
138  */
139 void ClearScrWithTmpPlt(UINT32 color);
140 
141 /*
142  * 停止使用临时调色板寄存器
143  */
144 void DisableTmpPlt(void);
145 
146 /*
147  * 改变调色板为一种颜色
148  * 输入参数:
149  *     color: 颜色值,格式为0xRRGGBB
150  */
151 void ChangePalette(UINT32 color);
152 
153 
154 #endif /*__LCDDRV_H__*/
lcddrv.h

 

  1 /*
  2  * FILE: lcddrv.c
  3  * 提供操作LCD控制器、调色板等的底层函数
  4  */
  5 
  6 #include <stdio.h>
  7 #include "s3c24xx.h"
  8 #include "lcddrv.h"
  9 
 10 #define GPB0_tout0  (2<<(0*2))
 11 #define GPB0_out    (1<<(0*2))
 12 #define GPB1_out    (1<<(1*2))
 13 
 14 #define GPB0_MSK    (3<<(0*2))
 15 #define GPB1_MSK    (3<<(1*2))
 16 
 17 
 18 unsigned int fb_base_addr;
 19 unsigned int bpp;
 20 unsigned int xsize;
 21 unsigned int ysize;
 22 
 23 static const unsigned short DEMO256pal[]={
 24     0x0b5e,0xce9a,0xffd9,0x9d99,0xb63a,0xae7c,0xdd71,0x6c57,0xfd4d,0x00ae,0x9c4d,0xb5f8,0xad96,0x0131,0x0176,0xefff,0xcedd,0x9556,0xe4bf,0x00b6,0x22b7,0x002b,0x89de,0x002c,0x57df,0xab5f,0x3031,0x14bf,0x797e,0x5391,0x93ab,0x7239,0x7453,0xafdf,0x71b9,0x8c92,0x014d,0x302e,0x5175,0x0029,0x0969,0x004e,0x2a6d,0x0021,0x3155,0x4b6e,0xd677,0xf6b6,0x9b5f,0x4bb5,0xffd5,0x0027,0xdfdf,0x74d8,0x1256,0x6bcd,0x9b08,0x2ab2,0xbd72,0x84b5,0xfe52,0xd4ad,0x00ad,0xfffc,0x422b,0x73b0,0x0024,0x5246,0x8e5e,0x28b3,0x0050,0x3b52,0x2a4a,0x3a74,0x8559,0x3356,0x1251,0x9abf,0x4034,0x40b1,
 25     0x8cb9,0x00b3,0x5c55,0xdf3d,0x61b7,0x1f5f,0x00d9,0x4c59,0x0926,0xac3f,0x925f,0x85bc,0x29d2,0xc73f,0xef5c,0xcb9f,0x827b,0x5279,0x4af5,0x01b9,0x4290,0xf718,0x126d,0x21a6,0x515e,0xefbd,0xd75e,0x42ab,0x00aa,0x10b3,0x7349,0x63b5,0x61a3,0xaadf,0xcb27,0x87df,0x6359,0xc7df,0x4876,0xb5bc,0x4114,0xfe2e,0xef5e,0x65be,0x43b9,0xe5df,0x21c9,0x7d16,0x6abb,0x5c11,0x49f7,0xbc0b,0x9e1a,0x3b0f,0x202b,0xff12,0x821b,0x842f,0xbccf,0xdefb,0x8a3e,0x68fa,0xa4f1,0x38ae,0x28b7,0x21ad,0x31d7,0x0073,0x182b,0x1831,0x3415,0xbdf6,0x2dbf,0x0a5d,0xc73d,0x182c,0x293e,0x7b3d,0x643d,0x3cbd,
 26     0x92dd,0x09d4,0x1029,0x7cdd,0x6239,0x182e,0x5aea,0x11eb,0x8abc,0x7bfa,0x00a7,0x2153,0x1853,0x1318,0x0109,0x54fa,0x72a7,0x89e3,0x01cf,0x3a07,0x7b17,0x1a14,0x2150,0x23dc,0x4142,0x1b33,0x00a4,0xf6df,0x08fc,0x18ae,0x3a7e,0x18d1,0xa51c,0xff5a,0x1a0f,0x28fa,0xdfbe,0x82de,0x60d7,0x1027,0x48fa,0x5150,0x6213,0x89d6,0x110d,0x9bbb,0xbedd,0x28e1,0x1925,0xf449,0xaa79,0xd5f4,0x693c,0x110a,0x2889,0x08a2,0x923d,0x10a6,0xd9bc,0x5b2e,0x32ec,0xcf7f,0x1025,0x2148,0x74b4,0x6d59,0x9d14,0x0132,0x00f0,0x56bf,0x00f1,0xffff,0x0173,0x0133,0x00b0,0x00b1,0xf7ff,0x08b1,0xfffe,0x08b0,
 27     0x0171,0xf7bf,0x10f3,0xf7fe,0x08ef,0x1192,0xefbe,0x1131,0x2177,0xff9f,0x1116,0xffbc,0x5914,0x22ef,0xb285,0xa6df,
 28 };
 29 
 30 /*
 31  * 初始化用于LCD的引脚
 32  */
 33 void Lcd_Port_Init(void)
 34 {
 35     GPCUP   = 0xffffffff;   // 禁止内部上拉
 36     GPCCON  = 0xaaaaaaaa;   // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND 
 37     GPDUP   = 0xffffffff;   // 禁止内部上拉
 38     GPDCON  = 0xaaaaaaaa;   // GPIO管脚用于VD[23:8]
 39       GPBCON &= ~(GPB0_MSK);  // Power enable pin
 40     GPBCON |= GPB0_out;
 41     GPBDAT &= ~(1<<0);            // Power off
 42     printf("Initializing GPIO ports..........\n");
 43 }
 44 
 45 /*
 46  * 初始化LCD控制器
 47  * 输入参数:
 48  * type: 显示模式
 49  *      MODE_TFT_8BIT_240320  : 240*320 8bpp的TFT LCD
 50  *      MODE_TFT_16BIT_240320 : 240*320 16bpp的TFT LCD
 51  *      MODE_TFT_8BIT_640480  : 640*480 8bpp的TFT LCD
 52  *      MODE_TFT_16BIT_640480 : 640*480 16bpp的TFT LCD
 53  */
 54 void Tft_Lcd_Init(int type)
 55 {
 56     switch(type)
 57     {
 58     case MODE_TFT_8BIT_240320:
 59         /* 
 60          * 设置LCD控制器的控制寄存器LCDCON1~5
 61          * 1. LCDCON1:
 62          *    设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
 63          *    选择LCD类型: TFT LCD   
 64          *    设置显示模式: 8BPP
 65          *    先禁止LCD信号输出
 66          * 2. LCDCON2/3/4:
 67          *    设置控制信号的时间参数
 68          *    设置分辨率,即行数及列数
 69          * 现在,可以根据公式计算出显示器的频率:
 70          * 当HCLK=100MHz时,
 71          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
 72          *              {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
 73          *              {2x(CLKVAL+1)/(HCLK)}]
 74          *            = 60Hz
 75          * 3. LCDCON5:
 76          *    设置显示模式为8BPP时,调色板中的数据格式: 5:6:5
 77          *    设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
 78          *    字节交换使能
 79          */
 80         LCDCON1 = (CLKVAL_TFT_240320<<8) | (LCDTYPE_TFT<<5) | \
 81                   (BPPMODE_8BPP<<1) | (ENVID_DISABLE<<0);
 82         LCDCON2 = (VBPD_240320<<24) | (LINEVAL_TFT_240320<<14) | \
 83                   (VFPD_240320<<6) | (VSPW_240320);
 84         LCDCON3 = (HBPD_240320<<19) | (HOZVAL_TFT_240320<<8) | (HFPD_240320);
 85         LCDCON4 = HSPW_240320;
 86         LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
 87                   (BSWP<<1);
 88 
 89         /*
 90          * 设置LCD控制器的地址寄存器LCDSADDR1~3
 91          * 帧内存与视口(view point)完全吻合,
 92          * 图像数据格式如下(8BPP时,帧缓冲区中的数据为调色板中的索引值):
 93          *         |----PAGEWIDTH----|
 94          *    y/x  0   1   2       239
 95          *     0   idx idx idx ... idx
 96          *     1   idx idx idx ... idx
 97          * 1. LCDSADDR1:
 98          *    设置LCDBANK、LCDBASEU
 99          * 2. LCDSADDR2:
100          *    设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
101          * 3. LCDSADDR3:
102          *    OFFSIZE等于0,PAGEWIDTH等于(240/2)
103          */
104         LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
105         LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
106                     (LINEVAL_TFT_240320+1)*(HOZVAL_TFT_240320+1)*1)>>1);
107         LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320/2);
108 
109         /* 禁止临时调色板寄存器 */
110         TPAL = 0;
111 
112         fb_base_addr = LCDFRAMEBUFFER;
113         bpp = 8;
114         xsize = 240;
115         ysize = 320;
116         
117         break;
118 
119     case MODE_TFT_16BIT_240320:
120         /* 
121          * 设置LCD控制器的控制寄存器LCDCON1~5
122          * 1. LCDCON1:
123          *    设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
124          *    选择LCD类型: TFT LCD   
125          *    设置显示模式: 16BPP
126          *    先禁止LCD信号输出
127          * 2. LCDCON2/3/4:
128          *    设置控制信号的时间参数
129          *    设置分辨率,即行数及列数
130          * 现在,可以根据公式计算出显示器的频率:
131          * 当HCLK=100MHz时,
132          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
133          *              {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
134          *              {2x(CLKVAL+1)/(HCLK)}]
135          *            = 60Hz
136          * 3. LCDCON5:
137          *    设置显示模式为16BPP时的数据格式: 5:6:5
138          *    设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
139          *    半字(2字节)交换使能
140          */
141         LCDCON1 = (CLKVAL_TFT_240320<<8) | (LCDTYPE_TFT<<5) | \
142                   (BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
143         LCDCON2 = (VBPD_240320<<24) | (LINEVAL_TFT_240320<<14) | \
144                   (VFPD_240320<<6) | (VSPW_240320);
145         LCDCON3 = (HBPD_240320<<19) | (HOZVAL_TFT_240320<<8) | (HFPD_240320);
146         LCDCON4 = HSPW_240320;
147         LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
148                   (HWSWP<<1);
149 
150         /*
151          * 设置LCD控制器的地址寄存器LCDSADDR1~3
152          * 帧内存与视口(view point)完全吻合,
153          * 图像数据格式如下:
154          *         |----PAGEWIDTH----|
155          *    y/x  0   1   2       239
156          *     0   rgb rgb rgb ... rgb
157          *     1   rgb rgb rgb ... rgb
158          * 1. LCDSADDR1:
159          *    设置LCDBANK、LCDBASEU
160          * 2. LCDSADDR2:
161          *    设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
162          * 3. LCDSADDR3:
163          *    OFFSIZE等于0,PAGEWIDTH等于(240*2/2)
164          */
165         LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
166         LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
167                     (LINEVAL_TFT_240320+1)*(HOZVAL_TFT_240320+1)*2)>>1);
168         LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320*2/2);
169 
170         /* 禁止临时调色板寄存器 */
171         TPAL = 0;
172 
173         fb_base_addr = LCDFRAMEBUFFER;
174         bpp = 16;
175         xsize = 240;
176         ysize = 320;
177 
178         break;
179 
180     case MODE_TFT_8BIT_640480:
181         /* 
182          * 设置LCD控制器的控制寄存器LCDCON1~5
183          * 1. LCDCON1:
184          *    设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
185          *    选择LCD类型: TFT LCD   
186          *    设置显示模式: 8BPP
187          *    先禁止LCD信号输出
188          * 2. LCDCON2/3/4:
189          *    设置控制信号的时间参数
190          *    设置分辨率,即行数及列数
191          * 现在,可以根据公式计算出显示器的频率:
192          * 当HCLK=100MHz时,
193          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
194          *              {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
195          *              {2x(CLKVAL+1)/(HCLK)}]
196          *            = 60Hz
197          * 3. LCDCON5:
198          *    设置显示模式为8BPP时,调色板中的数据格式: 5:6:5
199          *    设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
200          *    字节交换使能
201          */
202         LCDCON1 = (CLKVAL_TFT_640480<<8) | (LCDTYPE_TFT<<5) | \
203                   (BPPMODE_8BPP<<1) | (ENVID_DISABLE<<0);
204         LCDCON2 = (VBPD_640480<<24) | (LINEVAL_TFT_640480<<14) | \
205                   (VFPD_640480<<6) | (VSPW_640480);
206         LCDCON3 = (HBPD_640480<<19) | (HOZVAL_TFT_640480<<8) | (HFPD_640480);
207         LCDCON4 = HSPW_640480;
208         LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
209                   (BSWP<<1);
210 
211         /*
212          * 设置LCD控制器的地址寄存器LCDSADDR1~3
213          * 帧内存与视口(view point)完全吻合,
214          * 图像数据格式如下(8BPP时,帧缓冲区中的数据为调色板中的索引值):
215          *         |----PAGEWIDTH----|
216          *    y/x  0   1   2       639
217          *     0   idx idx idx ... idx
218          *     1   idx idx idx ... idx
219          * 1. LCDSADDR1:
220          *    设置LCDBANK、LCDBASEU
221          * 2. LCDSADDR2:
222          *    设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
223          * 3. LCDSADDR3:
224          *    OFFSIZE等于0,PAGEWIDTH等于(640/2)
225          */
226         LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
227         LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
228                     (LINEVAL_TFT_640480+1)*(HOZVAL_TFT_640480+1)*1)>>1);
229         LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480/2);
230 
231         /* 禁止临时调色板寄存器 */
232         TPAL = 0;
233 
234         fb_base_addr = LCDFRAMEBUFFER;
235         bpp = 8;
236         xsize = 640;
237         ysize = 480;
238         
239         break;
240         
241     case MODE_TFT_16BIT_640480:
242         /* 
243          * 设置LCD控制器的控制寄存器LCDCON1~5
244          * 1. LCDCON1:
245          *    设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
246          *    选择LCD类型: TFT LCD   
247          *    设置显示模式: 16BPP
248          *    先禁止LCD信号输出
249          * 2. LCDCON2/3/4:
250          *    设置控制信号的时间参数
251          *    设置分辨率,即行数及列数
252          * 现在,可以根据公式计算出显示器的频率:
253          * 当HCLK=100MHz时,
254          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
255          *              {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
256          *              {2x(CLKVAL+1)/(HCLK)}]
257          *            = 60Hz
258          * 3. LCDCON5:
259          *    设置显示模式为16BPP时的数据格式: 5:6:5
260          *    设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
261          *    半字(2字节)交换使能
262          */
263         LCDCON1 = (CLKVAL_TFT_640480<<8) | (LCDTYPE_TFT<<5) | \
264                   (BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
265         LCDCON2 = (VBPD_640480<<24) | (LINEVAL_TFT_640480<<14) | \
266                   (VFPD_640480<<6) | (VSPW_640480);
267         LCDCON3 = (HBPD_640480<<19) | (HOZVAL_TFT_640480<<8) | (HFPD_640480);
268         LCDCON4 = HSPW_640480;
269         LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
270                   (HWSWP<<1);
271 
272         /*
273          * 设置LCD控制器的地址寄存器LCDSADDR1~3
274          * 帧内存与视口(view point)完全吻合,
275          * 图像数据格式如下:
276          *         |----PAGEWIDTH----|
277          *    y/x  0   1   2       639
278          *     0   rgb rgb rgb ... rgb
279          *     1   rgb rgb rgb ... rgb
280          * 1. LCDSADDR1:
281          *    设置LCDBANK、LCDBASEU
282          * 2. LCDSADDR2:
283          *    设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
284          * 3. LCDSADDR3:
285          *    OFFSIZE等于0,PAGEWIDTH等于(640*2/2)
286          */
287         LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
288         LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
289                     (LINEVAL_TFT_640480+1)*(HOZVAL_TFT_640480+1)*2)>>1);
290         LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480*2/2);
291 
292         /* 禁止临时调色板寄存器 */
293         TPAL = 0;
294 
295         fb_base_addr = LCDFRAMEBUFFER;
296         bpp = 16;
297         xsize = 640;
298         ysize = 480;
299 
300         break;
301 
302     default:
303         break;
304     }   
305 }
306 
307 /*
308  * 设置调色板
309  */
310 void Lcd_Palette8Bit_Init(void)
311 {
312     int i;  
313     volatile unsigned int *palette;
314 
315     LCDCON1 &= ~0x01;    // stop lcd controller
316     
317     LCDCON5 |= (FORMAT8BPP_565<<11); // 设置调色板中数据格式为5:6:5
318 
319     palette = (volatile unsigned int *)PALETTE;
320     for (i = 0; i < 256; i++)
321         *palette++ = DEMO256pal[i];
322 
323     LCDCON1 |= 0x01;    // re-enable lcd controller
324 }
325 
326 /*
327  * 改变调色板为一种颜色
328  * 输入参数:
329  *     color: 颜色值,格式为0xRRGGBB
330  */
331 void ChangePalette(UINT32 color)
332 {
333     int i;
334     unsigned char red, green, blue;
335     UINT32 *palette;
336 
337     red   = (color >> 19) & 0x1f;
338     green = (color >> 10) & 0x3f;
339     blue  = (color >>  3) & 0x1f;
340     color = (red << 11) | (green << 5) | blue; // 格式5:6:5
341     
342     palette=(UINT32 *)PALETTE;
343     LCDCON1 &= ~0x01;    // stop lcd controller
344     for (i = 0; i < 256; i++)
345     {
346 //        while (((LCDCON5>>15) & 0x3) == 2);     // 等待直到VSTATUS不为”有效”
347         *palette++ = color;
348     }
349     LCDCON1 |= 0x01;    // re-enable lcd controller
350 }
351 
352 /*
353  * 设置是否输出LCD电源开关信号LCD_PWREN
354  * 输入参数:
355  *     invpwren: 0 - LCD_PWREN有效时为正常极性
356  *               1 - LCD_PWREN有效时为反转极性
357  *     pwren:    0 - LCD_PWREN输出有效
358  *               1 - LCD_PWREN输出无效
359  */
360 void Lcd_PowerEnable(int invpwren, int pwren)
361 {
362     GPGCON = (GPGCON & (~(3<<8))) | (3<<8);   // GPG4用作LCD_PWREN
363     GPGUP  = (GPGUP & (~(1<<4))) | (1<<4);    // 禁止内部上拉    
364         
365     LCDCON5 = (LCDCON5 & (~(1<<5))) | (invpwren<<5);  // 设置LCD_PWREN的极性: 正常/反转
366     LCDCON5 = (LCDCON5 & (~(1<<3))) | (pwren<<3);     // 设置是否输出LCD_PWREN
367 }    
368 
369 /*
370  * 设置LCD控制器是否输出信号
371  * 输入参数:
372  * onoff: 
373  *      0 : 关闭
374  *      1 : 打开
375  */
376 void Lcd_EnvidOnOff(int onoff)
377 {
378     if (onoff == 1)
379     {
380         LCDCON1 |= 1;         // ENVID ON
381         GPBDAT |= (1<<0);            // Power on
382     }
383     else
384     {
385         LCDCON1 &= 0x3fffe;  // ENVID Off
386         GPBDAT &= ~(1<<0);     // Power off
387     }
388 }    
389 
390 /*
391  * 使用临时调色板寄存器输出单色图像
392  * 输入参数:
393  *     color: 颜色值,格式为0xRRGGBB
394  */
395 void ClearScrWithTmpPlt(UINT32 color)
396 {
397     TPAL = (1<<24)|((color & 0xffffff)<<0);
398 }
399 
400 /*
401  * 停止使用临时调色板寄存器
402  */
403 void DisableTmpPlt(void)
404 {
405     TPAL = 0;
406 }
lcddrv.c

 

posted @ 2015-12-21 17:08  CAM&  阅读(1232)  评论(0编辑  收藏  举报