四、图像数据在内存中存储格式
显示器上每个像素的颜色由3部分组成:Red,Grean,Blue。它们称为三位原名,这三者组合几乎可以表示人眼能识别的所有颜色。
S3c2440的LCD控制器共支持单色(1BBP)、4级灰度(2BBP)、16级灰度(BBP)、256级灰度(8BBP)调色板模式,和64K(16BBP)与16M(24BBP)显示模式。下面介绍其中4种。
1) 16M(24BBP)
16M(24BBP)显示模式就是使用24位数据,每个原色使用8位。LCD控制器从内存中获得某个像素的24位颜色值后,直接通过VD[23:0]数据线来发送给LCD。为了方便DMA传输,在内存中使用4个字节(32)位来表示一个像素。
2)16M(24BBP)色
16M(24BBP)色的显示模式就是使用16位的数据来表示一个像素的颜色,分为5:6:5、5:5:5:1(即RGBA模式),前者有点一同处是绿色用6位来表示,后者的最后一位表示透明度。
3)256级灰度(8BBP)
256级灰度(8BBP)的显示模式就是使用8位数据来表示一个像素的颜色,平均下来每个原色只能使用不到3位的数据表示,即每个色不超过8个级别,不足以表示更丰富的色彩。为解决8BBP模式能力太弱的问题,需要使用调色板(palette)。每个像素对应的8位数据不再用来表示RGB三种原色,而是表示它在调色板中的索引值;显示使用这个索引值从调色板中取得RGB颜色值。
所谓调色板就是一块内存,对应每个索引值设置的颜色,可以使用(24BPP)或(16BPP)。S3C2440中调色板就是一块(256*16)的内存,使用(16BPP)的格式来表示(8BBP)显示模式下的各个索引值的颜色。这样即使(8BBP)显示模式也能表示(16BPP)的数据。
五、调色板(palette)
调色板中数据存放的格式与上面所描述的(16BPP)显示模式相似,也分为两种格式5:5:5:1,5:6:5。
六、寄存器设置
LCDCON1 0X4D000000 R/W LCD control 1 register 0x00000000
LINECNT:行计数器的状态位。只读,不用配置。
CLKVAL:确定VCLK频率的参数。公式为VCLK=HCLK/[(CLKVAL+1)×2]Hz。
MMODE:确定VM的改变速度。在此选择MMODE=O,为每帧变化模式。
PNRMODE:确定扫描方式。选择PNRMODE=0x3,为TFT LCD面板扫描模式。BPPMODE:确定BPP(每像素位数)模式。在此选择
BPPMODE=0xC,为TFT 16位模式。
ENVID:数据输出和逻辑信号使能控制位。选择ENVID=1,为允许数据输出和逻辑控制。
CDCON2 0X4D000004 R/W LCD control 2 register
VBPD:确定帧同步信号和帧数据传输前的一段延迟时间,是帧数据传输前延迟时间和行同步时钟间隔宽度的比值。
LINEVAL:确定显示的垂直方向尺寸。公式:LINEVAL=YSIZE-1=。
VFPD:确定帧数据传输完成后到下一帧同步信号到来的一段延迟时间,是帧数据传输后延迟时间和行同步时钟间隔宽度的比值。
VSPW:确定帧同步时钟脉冲宽度,是帧同步信号时钟宽度和行同步时钟间隔宽度的比值。
LCDCON3 0X4D000008 R/W LCD control 3 register
HBPD:确定行同步信号和行数据传输前的一段延迟时间,描述行数据传输前延迟时间内VCLK脉冲个数。
HOZAL:确定显示的水平方向尺寸。公式HOZAL=XSIZE-1。
HFPD:确定行数据传输完成后到下一行同步信号到来的一段延迟时间,描述行数据传输后延迟时间内VCLK脉冲个数。
LCDCON4 0X4D00000C R/W LCD control 4 register
HSPW:确定行同步时钟脉冲宽度。描述行同步脉冲宽度时间内VCLK脉冲个数。
LCDCON5 0X4D000010 R/W LCD control 5 register
VSTATUS:垂直方向状态。只读,不用配置。
HSTATUS:水平方向状态。只读,不用配置。
BPP24BL:确定显示数据存储格式。配置BPP24BL=0x0,为小端模式存放。
FRM565:确定16位数据输出格式。配置FRM565=0x1,为5:6:5格式输出。
INVVCLK:确定VCLK脉冲有效边沿极性。如INVVCLK=0xl,VCLK上升沿到来时数据传输开始。
INVVLlNE:确定HSYNC脉冲的极性。
INVVFRAME:确定VSYNC脉冲的极性。
INVVD:确定数据输出的脉冲极性。
INVVDEN:确定VDEN信号极性。
INVPWREN:确定PWREN信号极性。
INVLEND:确定LEND信号极性。
PWREN:PWREN信号输出允许。
ENLEND:LEND输出信号允许。
BSWP:字节交换控制位。如配置BSWP=0x0,禁止字节交换。
HWSWP:半字交换控制位。如配置HWSWP=0xl,使能半字节交换。
七、帧缓冲(FrameBuffer):
帧缓冲是Linux为显示设备提供的一个接口,它把一些显示设备描述成一个缓冲区,允许应用程序通过 FrameBuffer定义好的接口访问这些图形设备,从而不用去关心具体的硬件细节。对于帧缓冲设备而言,只要在显示缓冲区与显示点对应的区域写入颜色值,对应的颜色就会自动的在屏幕上显示。下面来看一下在不同色位模式下缓冲区与显示点的对应关系:
LCDSADDR1 0X4D000014 R/W STN/TFT: Frame buffer start address 1 register 0x00000000
LCDSADDR2 0X4D000018 R/W STN/TFT: Frame buffer start address 2 register 0x00000000
LCDSADDR3 0X4D00001C R/W STN/TFT: Virtual screen address set
八、硬件连接图
LCD CTRL
LCD DATA
九、关键代码分析
lcddrv.c //LCD底层驱动
- /*
- * FILE: lcddrv.c
- * 提供操作LCD控制器、调色板等的底层函数
- */
- #include <stdio.h>
- #include "s3c2440_addr.h"
- #include "lcddrv.h"
- unsigned int fb_base_addr;
- unsigned int bpp;
- unsigned int xsize;
- unsigned int ysize;
- static const unsigned short DEMO256pal[]={
- 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,
- 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,
- 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,
- 0x0171,0xf7bf,0x10f3,0xf7fe,0x08ef,0x1192,0xefbe,0x1131,0x2177,0xff9f,0x1116,0xffbc,0x5914,0x22ef,0xb285,0xa6df,
- };
- /*
- * 初始化用于LCD的引脚
- */
- void Lcd_Port_Init(void)
- {
- GPCUP = 0xffffffff; // 禁止内部上拉
- GPCCON = 0xaaaa02a8; // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND
- GPDUP = 0xffffffff; // 禁止内部上拉
- GPDCON = 0xaaaaaaaa; // GPIO管脚用于VD[23:8]
- printf("Initializing GPIO ports for LCD..........\r\n");
- }
- /*
- * 初始化LCD控制器
- * 输入参数:
- * type: 显示模式
- * MODE_TFT_8BIT_240320 : 240*320 8bpp的TFT LCD
- * MODE_TFT_16BIT_240320 : 240*320 16bpp的TFT LCD
- * MODE_TFT_8BIT_640480 : 640*480 8bpp的TFT LCD
- * MODE_TFT_16BIT_640480 : 640*480 16bpp的TFT LCD
- */
- void Tft_Lcd_Init(int type)
- {
- switch(type)
- {
- case MODE_TFT_8BIT_240320:
- /*
- * 设置LCD控制器的控制寄存器LCDCON1~5
- * 1. LCDCON1:
- * HCLK=100Hz
- * 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]=10Hz
- * 选择LCD类型: TFT LCD
- * 设置显示模式: 8BPP
- * 先禁止LCD信号输出
- * 2. LCDCON2/3/4:
- * 设置控制信号的时间参数
- * 设置分辨率,即行数及列数
- * 现在,可以根据公式计算出显示器的频率:
- * 当HCLK=100MHz时,
- * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
- * {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
- * {2x(CLKVAL+1)/(HCLK)}]
- * = 60Hz
- * 3. LCDCON5:
- * 设置显示模式为8BPP时,调色板中的数据格式: 5:6:5
- * 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
- * 字节交换使能
- */
- LCDCON1 = (CLKVAL_TFT_240320<<8) | (LCDTYPE_TFT<<5) | \
- (BPPMODE_8BPP<<1) | (ENVID_DISABLE<<0);
- LCDCON2 = (VBPD_240320<<24) | (LINEVAL_TFT_240320<<14) | \
- (VFPD_240320<<6) | (VSPW_240320);
- LCDCON3 = (HBPD_240320<<19) | (HOZVAL_TFT_240320<<8) | (HFPD_240320);
- LCDCON4 = HSPW_240320;
- LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
- (BSWP<<1);
- /*
- * 设置LCD控制器的地址寄存器LCDSADDR1~3
- * 帧内存与视口(view point)完全吻合,
- * 图像数据格式如下(8BPP时,帧缓冲区中的数据为调色板中的索引值):
- * |----PAGEWIDTH----|
- * y/x 0 1 2 239
- * 0 idx idx idx ... idx
- * 1 idx idx idx ... idx
- * 1. LCDSADDR1:
- * 设置LCDBANK、LCDBASEU
- * 2. LCDSADDR2:
- * 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
- * 3. LCDSADDR3:
- * OFFSIZE等于0,PAGEWIDTH等于(240/2)
- */
- LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
- LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+(LINEVAL_TFT_240320+1)*(HOZVAL_TFT_240320+1)*1)>>1);
- LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320/2);
- /* 禁止临时调色板寄存器 */
- TPAL = 0;
- fb_base_addr = LCDFRAMEBUFFER;
- bpp = 8;
- xsize = 240;
- ysize = 320;
-
- break;
-
- case MODE_TFT_16BIT_240320:
- /*
- * 设置LCD控制器的控制寄存器LCDCON1~5
- * 1. LCDCON1:
- * 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
- * 选择LCD类型: TFT LCD
- * 设置显示模式: 16BPP
- * 先禁止LCD信号输出
- * 2. LCDCON2/3/4:
- * 设置控制信号的时间参数
- * 设置分辨率,即行数及列数
- * 现在,可以根据公式计算出显示器的频率:
- * 当HCLK=100MHz时,
- * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
- * {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
- * {2x(CLKVAL+1)/(HCLK)}]
- * = 60Hz
- * 3. LCDCON5:
- * 设置显示模式为16BPP时的数据格式: 5:6:5
- * 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
- * 半字(2字节)交换使能
- */
- LCDCON1 = (CLKVAL_TFT_240320<<8) | (LCDTYPE_TFT<<5) | \
- (BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
- LCDCON2 = (VBPD_240320<<24) | (LINEVAL_TFT_240320<<14) | \
- (VFPD_240320<<6) | (VSPW_240320);
- LCDCON3 = (HBPD_240320<<19) | (HOZVAL_TFT_240320<<8) | (HFPD_240320);
- LCDCON4 = HSPW_240320;
- LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
- (HWSWP<<1);
- /*
- * 设置LCD控制器的地址寄存器LCDSADDR1~3
- * 帧内存与视口(view point)完全吻合,
- * 图像数据格式如下:
- * |----PAGEWIDTH----|
- * y/x 0 1 2 239
- * 0 rgb rgb rgb ... rgb
- * 1 rgb rgb rgb ... rgb
- * 1. LCDSADDR1:
- * 设置LCDBANK、LCDBASEU
- * 2. LCDSADDR2:
- * 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
- * 3. LCDSADDR3:
- * OFFSIZE等于0,PAGEWIDTH等于(240*2/2)
- */
- LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
- LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
- (LINEVAL_TFT_240320+1)*(HOZVAL_TFT_240320+1)*2)>>1);
- LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320*2/2);
- /* 禁止临时调色板寄存器 */
- TPAL = 0;
- fb_base_addr = LCDFRAMEBUFFER;
- bpp = 16;
- xsize = 240;
- ysize = 320;
- break;
-
- case MODE_TFT_8BIT_640480:
- /*
- * 设置LCD控制器的控制寄存器LCDCON1~5
- * 1. LCDCON1:
- * 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
- * 选择LCD类型: TFT LCD
- * 设置显示模式: 8BPP
- * 先禁止LCD信号输出
- * 2. LCDCON2/3/4:
- * 设置控制信号的时间参数
- * 设置分辨率,即行数及列数
- * 现在,可以根据公式计算出显示器的频率:
- * 当HCLK=100MHz时,
- * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
- * {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
- * {2x(CLKVAL+1)/(HCLK)}]
- * = 60Hz
- * 3. LCDCON5:
- * 设置显示模式为8BPP时,调色板中的数据格式: 5:6:5
- * 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
- * 字节交换使能
- */
- LCDCON1 = (CLKVAL_TFT_640480<<8) | (LCDTYPE_TFT<<5) | \
- (BPPMODE_8BPP<<1) | (ENVID_DISABLE<<0);
- LCDCON2 = (VBPD_640480<<24) | (LINEVAL_TFT_640480<<14) | \
- (VFPD_640480<<6) | (VSPW_640480);
- LCDCON3 = (HBPD_640480<<19) | (HOZVAL_TFT_640480<<8) | (HFPD_640480);
- LCDCON4 = HSPW_640480;
- LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
- (BSWP<<1);
- /*
- * 设置LCD控制器的地址寄存器LCDSADDR1~3
- * 帧内存与视口(view point)完全吻合,
- * 图像数据格式如下(8BPP时,帧缓冲区中的数据为调色板中的索引值):
- * |----PAGEWIDTH----|
- * y/x 0 1 2 639
- * 0 idx idx idx ... idx
- * 1 idx idx idx ... idx
- * 1. LCDSADDR1:
- * 设置LCDBANK、LCDBASEU
- * 2. LCDSADDR2:
- * 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
- * 3. LCDSADDR3:
- * OFFSIZE等于0,PAGEWIDTH等于(640/2)
- */
- LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
- LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
- (LINEVAL_TFT_640480+1)*(HOZVAL_TFT_640480+1)*1)>>1);
- LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480/2);
- /* 禁止临时调色板寄存器 */
- TPAL = 0;
- fb_base_addr = LCDFRAMEBUFFER;
- bpp = 8;
- xsize = 640;
- ysize = 480;
-
- break;
-
- case MODE_TFT_16BIT_640480:
- /*
- * 设置LCD控制器的控制寄存器LCDCON1~5
- * 1. LCDCON1:
- * 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
- * 选择LCD类型: TFT LCD
- * 设置显示模式: 16BPP
- * 先禁止LCD信号输出
- * 2. LCDCON2/3/4:
- * 设置控制信号的时间参数
- * 设置分辨率,即行数及列数
- * 现在,可以根据公式计算出显示器的频率:
- * 当HCLK=100MHz时,
- * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
- * {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
- * {2x(CLKVAL+1)/(HCLK)}]
- * = 60Hz
- * 3. LCDCON5:
- * 设置显示模式为16BPP时的数据格式: 5:6:5
- * 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
- * 半字(2字节)交换使能
- */
- LCDCON1 = (CLKVAL_TFT_640480<<8) | (LCDTYPE_TFT<<5) | \
- (BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
- LCDCON2 = (VBPD_640480<<24) | (LINEVAL_TFT_640480<<14) | \
- (VFPD_640480<<6) | (VSPW_640480);
- LCDCON3 = (HBPD_640480<<19) | (HOZVAL_TFT_640480<<8) | (HFPD_640480);
- LCDCON4 = HSPW_640480;
- LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
- (HWSWP<<1);
- /*
- * 设置LCD控制器的地址寄存器LCDSADDR1~3
- * 帧内存与视口(view point)完全吻合,
- * 图像数据格式如下:
- * |----PAGEWIDTH----|
- * y/x 0 1 2 639
- * 0 rgb rgb rgb ... rgb
- * 1 rgb rgb rgb ... rgb
- * 1. LCDSADDR1:
- * 设置LCDBANK、LCDBASEU
- * 2. LCDSADDR2:
- * 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
- * 3. LCDSADDR3:
- * OFFSIZE等于0,PAGEWIDTH等于(640*2/2)
- */
- LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
- LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
- (LINEVAL_TFT_640480+1)*(HOZVAL_TFT_640480+1)*2)>>1);
- LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480*2/2);
- /* 禁止临时调色板寄存器 */
- TPAL = 0;
- fb_base_addr = LCDFRAMEBUFFER;
- bpp = 16;
- xsize = 640;
- ysize = 480;
- break;
- default:
- break;
- }
- }
- /*
- * 设置调色板
- */
- void Lcd_Palette8Bit_Init(void)
- {
- int i;
- volatile unsigned int *palette;
-
- LCDCON5 |= (FORMAT8BPP_565<<11); // 设置调色板中数据格式为5:6:5
- palette = (volatile unsigned int *)PALETTE;
- for (i = 0; i < 256; i++)
- *palette++ = DEMO256pal[i];
- }
- /*
- * 改变调色板为一种颜色
- * 输入参数:
- * color: 颜色值,格式为0xRRGGBB
- */
- void ChangePalette(UINT32 color)
- {
- int i;
- unsigned char red, green, blue;
- UINT32 *palette;
-
- palette=(UINT32 *)PALETTE;
- for (i = 0; i < 256; i++)
- {
- red = (color >> 19) & 0xff;
- green = (color >> 10) & 0xff;
- blue = (color >> 3) & 0xff;
- color = (red << 11) | (green << 5) | blue; // 格式5:6:5
- while ((LCDCON5>>16) == 2); // 等待直到VSTATUS不为”有效”
- *palette++ = color;
- }
- }
- /*
- * 设置是否输出LCD电源开关信号LCD_PWREN
- * 输入参数:
- * invpwren: 0 - LCD_PWREN有效时为正常极性
- * 1 - LCD_PWREN有效时为反转极性
- * pwren: 0 - LCD_PWREN输出有效
- * 1 - LCD_PWREN输出无效
- */
- void Lcd_PowerEnable(int invpwren, int pwren)
- {
- GPGCON = (GPGCON & (~(3<<8))) | (3<<8); // GPG4用作LCD_PWREN
- GPGUP = (GPGUP & (~(1<<4))) | (1<<4); // 禁止内部上拉
-
- LCDCON5 = (LCDCON5 & (~(1<<5))) | (invpwren<<5); // 设置LCD_PWREN的极性: 正常/反转
- LCDCON5 = (LCDCON5 & (~(1<<3))) | (pwren<<3); // 设置是否输出LCD_PWREN
- }
- /*
- * 设置LCD控制器是否输出信号
- * 输入参数:
- * onoff:
- * 0 : 关闭
- * 1 : 打开
- */
- void Lcd_EnvidOnOff(int onoff)
- {
- if (onoff == 1)
- LCDCON1 |= 1; // ENVID ON
- else
- LCDCON1 &= 0x3fffe; // ENVID Off
- }
- /*
- * 使用临时调色板寄存器输出单色图像
- * 输入参数:
- * color: 颜色值,格式为0xRRGGBB
- */
- void ClearScrWithTmpPlt(UINT32 color)
- {
- TPAL = (1<<24)|((color & 0xffffff)<<0);
- }
- /*
- * 停止使用临时调色板寄存器
- */
- void DisableTmpPlt(void)
- {
- TPAL = 0;
- }
framebuffer.c //绘制像素点,直线,圆
- /*
- * FILE: framebuffer.c
- * 实现在framebuffer上画点、画线、画同心圆、清屏的函数
- */
- #include "framebuffer.h"
- extern unsigned int fb_base_addr;
- extern unsigned int bpp;
- extern unsigned int xsize;
- extern unsigned int ysize;
- /*
- * 画点
- * 输入参数:
- * x、y : 象素坐标
- * color: 颜色值
- * 对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
- * 需要转换为5:6:5格式
- * 对于8BPP: color为调色板中的索引值,
- * 其颜色取决于调色板中的数值
- */
- void PutPixel(UINT32 x, UINT32 y, UINT32 color)
- {
- UINT8 red,green,blue;
- switch (bpp){
- case 16:
- {
- UINT16 *addr = (UINT16 *)fb_base_addr + (y * xsize + x);
- red = (color >> 19) & 0xff;
- green = (color >> 10) & 0xff;
- blue = (color >> 3) & 0xff;
- color = (red << 11) | (green << 5) | blue; // 格式5:6:5
- *addr = (UINT16) color;
- break;
- }
-
- case 8:
- {
- UINT8 *addr = (UINT8 *)fb_base_addr + (y * xsize + x);
- *addr = (UINT8) color;
- break;
- }
- default:
- break;
- }
- }
- /*
- * 画线
- * 输入参数:
- * x1、y1 : 起点坐标
- * x2、y2 : 终点坐标
- * color : 颜色值
- * 对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
- * 需要转换为5:6:5格式
- * 对于8BPP: color为调色板中的索引值,
- * 其颜色取决于调色板中的数值
- */
- void DrawLine(int x1,int y1,int x2,int y2,int color)
- {
- int dx,dy,e;
- dx=x2-x1;
- dy=y2-y1;
-
- if(dx>=0)
- {
- if(dy >= 0) // dy>=0
- {
- if(dx>=dy) // 1/8 octant
- {
- e=dy-dx/2;
- while(x1<=x2)
- {
- PutPixel(x1,y1,color);
- if(e>0){y1+=1;e-=dx;}
- x1+=1;
- e+=dy;
- }
- }
- else // 2/8 octant
- {
- e=dx-dy/2;
- while(y1<=y2)
- {
- PutPixel(x1,y1,color);
- if(e>0){x1+=1;e-=dy;}
- y1+=1;
- e+=dx;
- }
- }
- }
- else // dy<0
- {
- dy=-dy; // dy=abs(dy)
- if(dx>=dy) // 8/8 octant
- {
- e=dy-dx/2;
- while(x1<=x2)
- {
- PutPixel(x1,y1,color);
- if(e>0){y1-=1;e-=dx;}
- x1+=1;
- e+=dy;
- }
- }
- else // 7/8 octant
- {
- e=dx-dy/2;
- while(y1>=y2)
- {
- PutPixel(x1,y1,color);
- if(e>0){x1+=1;e-=dy;}
- y1-=1;
- e+=dx;
- }
- }
- }
- }
- else //dx<0
- {
- dx=-dx; //dx=abs(dx)
- if(dy >= 0) // dy>=0
- {
- if(dx>=dy) // 4/8 octant
- {
- e=dy-dx/2;
- while(x1>=x2)
- {
- PutPixel(x1,y1,color);
- if(e>0){y1+=1;e-=dx;}
- x1-=1;
- e+=dy;
- }
- }
- else // 3/8 octant
- {
- e=dx-dy/2;
- while(y1<=y2)
- {
- PutPixel(x1,y1,color);
- if(e>0){x1-=1;e-=dy;}
- y1+=1;
- e+=dx;
- }
- }
- }
- else // dy<0
- {
- dy=-dy; // dy=abs(dy)
- if(dx>=dy) // 5/8 octant
- {
- e=dy-dx/2;
- while(x1>=x2)
- {
- PutPixel(x1,y1,color);
- if(e>0){y1-=1;e-=dx;}
- x1-=1;
- e+=dy;
- }
- }
- else // 6/8 octant
- {
- e=dx-dy/2;
- while(y1>=y2)
- {
- PutPixel(x1,y1,color);
- if(e>0){x1-=1;e-=dy;}
- y1-=1;
- e+=dx;
- }
- }
- }
- }
- }
- /*
- * 绘制同心圆
- */
- void Mire(void)
- {
- UINT32 x,y;
- UINT32 color;
- UINT8 red,green,blue,alpha;
- for (y = 0; y < ysize; y++)
- for (x = 0; x < xsize; x++){
- color = ((x-xsize/2)*(x-xsize/2) + (y-ysize/2)*(y-ysize/2))/64;
- red = (color/8) % 256;
- green = (color/4) % 256;
- blue = (color/2) % 256;
- alpha = (color*2) % 256;
- color |= ((UINT32)alpha << 24);
- color |= ((UINT32)red << 16);
- color |= ((UINT32)green << 8 );
- color |= ((UINT32)blue );
- PutPixel(x,y,color);
- }
- }
- /*
- * 将屏幕清成单色
- * 输入参数:
- * color: 颜色值
- * 对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
- * 需要转换为5:6:5格式
- * 对于8BPP: color为调色板中的索引值,
- * 其颜色取决于调色板中的数值
- */
- void ClearScr(UINT32 color)
- {
- UINT32 x,y;
-
- for (y = 0; y < ysize; y++)
- for (x = 0; x < xsize; x++)
- PutPixel(x, y, color);
- }
lcdlib.c //LCD测试
- /*
- * FILE: lcdlib.c
- * 实现TFT LCD的测试函数
- */
- #include <stdio.h>
- #include "lcddrv.h"
- #include "framebuffer.h"
- /*
- * 以240x320,8bpp的显示模式测试TFT LCD
- */
- void Test_Lcd_Tft_8Bit_240320(void)
- {
- Lcd_Port_Init(); // 设置LCD引脚
- Tft_Lcd_Init(MODE_TFT_8BIT_240320); // 初始化LCD控制器
- Lcd_PowerEnable(0, 1); // 设置LCD_PWREN有效,它用于打开LCD的电源
- Lcd_EnvidOnOff(1); // 使能LCD控制器输出信号
- Lcd_Palette8Bit_Init(); // 初始化调色板
- ClearScr(0x0); // 清屏
- printf("\n\r[TFT 64K COLOR(16bpp) LCD TEST]\n\r");
- printf("1. Press any key to draw line\n");
- getc();
- DrawLine(0 , 0 , 239, 0 , 0); // 颜色为DEMO256pal[0]
- DrawLine(0 , 0 , 0 , 239, 1); // 颜色为DEMO256pal[1]
- DrawLine(239, 0 , 239, 319, 2); // ……
- DrawLine(0 , 319, 239, 319, 4);
- DrawLine(0 , 0 , 239, 319, 8);
- DrawLine(239, 0 , 0 , 319, 16);
- DrawLine(120, 0 , 120, 319, 32);
- DrawLine(0 , 160, 239, 160, 64);
- printf("2. Press any key to draw circles\n");
- getc();
- Mire();
- printf("3. Press any key to fill the screem with one color\n");
- getc();
- ClearScr(128); // 输出单色图像,颜色为DEMO256pal[128]
- printf("4. Press any key to fill the screem by temporary palette\n");
- getc();
- ClearScrWithTmpPlt(0x0000ff); // 输出单色图像,颜色为蓝色
- printf("5. Press any key to fill the screem by palette\n");
- getc();
- DisableTmpPlt(); // 关闭临时调色板寄存器
- ChangePalette(0xffff00); // 改变整个调色板为黄色,输出单色图像
-
- printf("6. Press any key stop the testing\n");
- getc();
- Lcd_EnvidOnOff(0);
- }
- /*
- * 以240x320,16bpp的显示模式测试TFT LCD
- */
- void Test_Lcd_Tft_16Bit_240320(void)
- {
- Lcd_Port_Init(); // 设置LCD引脚
- Tft_Lcd_Init(MODE_TFT_16BIT_240320); // 初始化LCD控制器
- Lcd_PowerEnable(0, 1); // 设置LCD_PWREN有效,它用于打开LCD的电源
- Lcd_EnvidOnOff(1); // 使能LCD控制器输出信号
- ClearScr(0x0); // 清屏,黑色
- printf("\n\r[TFT 64K COLOR(16bpp) LCD TEST]\n\r");
- printf("1. Press any key to draw line\n");
- getc();
- DrawLine(0 , 0 , 239, 0 , 0xff0000); // 绿色
- DrawLine(0 , 0 , 0 , 319, 0x00ff00); // 红色
- DrawLine(239, 0 , 239, 319, 0x0000ff); // 蓝色
- DrawLine(0 , 319, 239, 319, 0xffffff); // 白色
- DrawLine(0 , 0 , 239, 319, 0xffff00); // 黄色
- DrawLine(239, 0 , 0 , 319, 0x8000ff); // 紫色
- DrawLine(120, 0 , 120, 319, 0xe6e8fa); // 银色
- DrawLine(0 , 160, 239, 160, 0xcd7f32); // 金色
- printf("2. Press any key to draw circles\n");
- getc();
- Mire();
- printf("3. Press any key to fill the screem with one color\n");
- getc();
- ClearScr(0xff0000); // 红色
- printf("4. Press any key to fill the screem by temporary palette\n");
- getc();
- ClearScrWithTmpPlt(0x0000ff); // 蓝色
- printf("5. Press any key stop the testing\n");
- getc();
- Lcd_EnvidOnOff(0);
- }
- /*
- * 以640x480,8bpp的显示模式测试TFT LCD
- */
- void Test_Lcd_Tft_8Bit_640480(void)
- {
- Lcd_Port_Init(); // 设置LCD引脚
- Tft_Lcd_Init(MODE_TFT_8BIT_640480); // 初始化LCD控制器
- Lcd_PowerEnable(0, 1); // 设置LCD_PWREN有效,它用于打开LCD的电源
- Lcd_EnvidOnOff(1); // 使能LCD控制器输出信号
- Lcd_Palette8Bit_Init(); // 初始化调色板
- ClearScr(0x0); // 清屏,黑色
- printf("[TFT 64K COLOR(16bpp) LCD TEST]\n");
- printf("1. Press any key to draw line\n");
- getc();
- DrawLine(0 , 0 , 639, 0 , 0); // 颜色为DEMO256pal[0]
- DrawLine(0 , 0 , 0 , 479, 1); // 颜色为DEMO256pal[1]
- DrawLine(639, 0 , 639, 479, 2); // ……
- DrawLine(0 , 479, 639, 479, 4);
- DrawLine(0 , 0 , 639, 479, 8);
- DrawLine(639, 0 , 0 , 479, 16);
- DrawLine(320, 0 , 320, 479, 32);
- DrawLine(0 , 240, 639, 240, 64);
- printf("2. Press any key to draw circles\n");
- getc();
- Mire();
- printf("3. Press any key to fill the screem with one color\n");
- getc();
- ClearScr(128); // 输出单色图像,颜色为DEMO256pal[128]
- printf("4. Press any key to fill the screem by temporary palette\n");
- getc();
- ClearScrWithTmpPlt(0x0000ff); // 输出单色图像,颜色为蓝色
-
- printf("5. Press any key to fill the screem by palette\n");
- getc();
- DisableTmpPlt(); // 关闭临时调色板寄存器
- ChangePalette(0xffff00); // 改变整个调色板为黄色,输出单色图像
-
- printf("6. Press any key stop the testing\n");
- getc();
- Lcd_EnvidOnOff(0);
- }
- /*
- * 以640x480,16bpp的显示模式测试TFT LCD
- */
- void Test_Lcd_Tft_16Bit_640480(void)
- {
- Lcd_Port_Init(); // 设置LCD引脚
- Tft_Lcd_Init(MODE_TFT_16BIT_640480); // 初始化LCD控制器
- Lcd_PowerEnable(0, 1); // 设置LCD_PWREN有效,它用于打开LCD的电源
- Lcd_EnvidOnOff(1); // 使能LCD控制器输出信号
- ClearScr(0x0); // 清屏,黑色
- printf("[TFT 64K COLOR(16bpp) LCD TEST]\n");
- printf("1. Press any key to draw line\n");
- getc();
- DrawLine(0 , 0 , 639, 0 , 0xff0000); // 红色
- DrawLine(0 , 0 , 0 , 479, 0x00ff00); // 绿色
- DrawLine(639, 0 , 639, 479, 0x0000ff); // 蓝色
- DrawLine(0 , 479, 639, 479, 0xffffff); // 白色
- DrawLine(0 , 0 , 639, 479, 0xffff00); // 黄色
- DrawLine(639, 0 , 0 , 479, 0x8000ff); // 紫色
- DrawLine(320, 0 , 320, 479, 0xe6e8fa); // 银色
- DrawLine(0 , 240, 639, 240, 0xcd7f32); // 金色
- printf("2. Press any key to draw circles\n");
- getc();
- Mire();
- printf("3. Press any key to fill the screem with one color\n");
- getc();
- ClearScr(0xff0000); // 红色
- printf("4. Press any key to fill the screem by temporary palette\n");
- getc();
- ClearScrWithTmpPlt(0x0000ff); // 蓝色
- printf("5. Press any key stop the testing\n");
- getc();
- Lcd_EnvidOnOff(0);
- }
十、运行效果图
以下为能直接运行的二进制文件,下载到Nand Flash Black0 直接以Nand Flash运行。
阅读(1961) | 评论(0) | 转发(0) |