Chinaunix首页 | 论坛 | 博客
  • 博客访问: 306334
  • 博文数量: 63
  • 博客积分: 1482
  • 博客等级: 上尉
  • 技术积分: 1185
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-12 19:06
个人简介

hello world!

文章分类

全部博文(63)

分类: LINUX

2011-03-24 10:34:41

四、图像数据在内存中存储格式

显示器上每个像素的颜色由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底层驱动

  1. /*
  2.  * FILE: lcddrv.c
  3.  * 提供操作LCD控制器、调色板等的底层函数
  4.  */

  5. #include <stdio.h>
  6. #include "s3c2440_addr.h"
  7. #include "lcddrv.h"

  8. unsigned int fb_base_addr;
  9. unsigned int bpp;
  10. unsigned int xsize;
  11. unsigned int ysize;

  12. static const unsigned short DEMO256pal[]={
  13.     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,
  14.     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,
  15.     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,
  16.     0x0171,0xf7bf,0x10f3,0xf7fe,0x08ef,0x1192,0xefbe,0x1131,0x2177,0xff9f,0x1116,0xffbc,0x5914,0x22ef,0xb285,0xa6df,
  17. };

  18. /*
  19.  * 初始化用于LCD的引脚
  20.  */
  21. void Lcd_Port_Init(void)
  22. {
  23.     GPCUP = 0xffffffff; // 禁止内部上拉

  24.     GPCCON = 0xaaaa02a8; // GPIO管脚用于VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND

  25.     GPDUP = 0xffffffff; // 禁止内部上拉

  26.     GPDCON = 0xaaaaaaaa; // GPIO管脚用于VD[23:8]

  27.     printf("Initializing GPIO ports for LCD..........\r\n");
  28. }

  29. /*
  30.  * 初始化LCD控制器
  31.  * 输入参数:
  32.  * type: 显示模式
  33.  * MODE_TFT_8BIT_240320 : 240*320 8bpp的TFT LCD
  34.  * MODE_TFT_16BIT_240320 : 240*320 16bpp的TFT LCD
  35.  * MODE_TFT_8BIT_640480 : 640*480 8bpp的TFT LCD
  36.  * MODE_TFT_16BIT_640480 : 640*480 16bpp的TFT LCD
  37.  */
  38. void Tft_Lcd_Init(int type)
  39. {
  40.     switch(type)
  41.     {
  42.     case MODE_TFT_8BIT_240320:
  43.         /*
  44.          * 设置LCD控制器的控制寄存器LCDCON1~5
  45.          * 1. LCDCON1:
  46.          *        HCLK=100Hz
  47.          * 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]=10Hz
  48.          * 选择LCD类型: TFT LCD
  49.          * 设置显示模式: 8BPP
  50.          * 先禁止LCD信号输出
  51.          * 2. LCDCON2/3/4:
  52.          * 设置控制信号的时间参数
  53.          * 设置分辨率,即行数及列数
  54.          * 现在,可以根据公式计算出显示器的频率:
  55.          * 当HCLK=100MHz时,
  56.          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
  57.          * {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
  58.          * {2x(CLKVAL+1)/(HCLK)}]
  59.          * = 60Hz
  60.          * 3. LCDCON5:
  61.          * 设置显示模式为8BPP时,调色板中的数据格式: 5:6:5
  62.          * 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
  63.          * 字节交换使能
  64.          */
  65.         LCDCON1 = (CLKVAL_TFT_240320<<8) | (LCDTYPE_TFT<<5) | \
  66.                   (BPPMODE_8BPP<<1) | (ENVID_DISABLE<<0);
  67.         LCDCON2 = (VBPD_240320<<24) | (LINEVAL_TFT_240320<<14) | \
  68.                   (VFPD_240320<<6) | (VSPW_240320);
  69.         LCDCON3 = (HBPD_240320<<19) | (HOZVAL_TFT_240320<<8) | (HFPD_240320);
  70.         LCDCON4 = HSPW_240320;
  71.         LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
  72.                   (BSWP<<1);

  73.         /*
  74.          * 设置LCD控制器的地址寄存器LCDSADDR1~3
  75.          * 帧内存与视口(view point)完全吻合,
  76.          * 图像数据格式如下(8BPP时,帧缓冲区中的数据为调色板中的索引值):
  77.          * |----PAGEWIDTH----|
  78.          * y/x 0 1 2 239
  79.          * 0 idx idx idx ... idx
  80.          * 1 idx idx idx ... idx
  81.          * 1. LCDSADDR1:
  82.          * 设置LCDBANK、LCDBASEU
  83.          * 2. LCDSADDR2:
  84.          * 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
  85.          * 3. LCDSADDR3:
  86.          * OFFSIZE等于0,PAGEWIDTH等于(240/2)
  87.          */
  88.         LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
  89.         LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+(LINEVAL_TFT_240320+1)*(HOZVAL_TFT_240320+1)*1)>>1);
  90.         LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320/2);

  91.         /* 禁止临时调色板寄存器 */
  92.         TPAL = 0;

  93.         fb_base_addr = LCDFRAMEBUFFER;
  94.         bpp = 8;
  95.         xsize = 240;
  96.         ysize = 320;
  97.         
  98.         break;
  99.         
  100.     case MODE_TFT_16BIT_240320:
  101.         /*
  102.          * 设置LCD控制器的控制寄存器LCDCON1~5
  103.          * 1. LCDCON1:
  104.          * 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
  105.          * 选择LCD类型: TFT LCD
  106.          * 设置显示模式: 16BPP
  107.          * 先禁止LCD信号输出
  108.          * 2. LCDCON2/3/4:
  109.          * 设置控制信号的时间参数
  110.          * 设置分辨率,即行数及列数
  111.          * 现在,可以根据公式计算出显示器的频率:
  112.          * 当HCLK=100MHz时,
  113.          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
  114.          * {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
  115.          * {2x(CLKVAL+1)/(HCLK)}]
  116.          * = 60Hz
  117.          * 3. LCDCON5:
  118.          * 设置显示模式为16BPP时的数据格式: 5:6:5
  119.          * 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
  120.          * 半字(2字节)交换使能
  121.          */
  122.         LCDCON1 = (CLKVAL_TFT_240320<<8) | (LCDTYPE_TFT<<5) | \
  123.                   (BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
  124.         LCDCON2 = (VBPD_240320<<24) | (LINEVAL_TFT_240320<<14) | \
  125.                   (VFPD_240320<<6) | (VSPW_240320);
  126.         LCDCON3 = (HBPD_240320<<19) | (HOZVAL_TFT_240320<<8) | (HFPD_240320);
  127.         LCDCON4 = HSPW_240320;
  128.         LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
  129.                   (HWSWP<<1);

  130.         /*
  131.          * 设置LCD控制器的地址寄存器LCDSADDR1~3
  132.          * 帧内存与视口(view point)完全吻合,
  133.          * 图像数据格式如下:
  134.          * |----PAGEWIDTH----|
  135.          * y/x 0 1 2 239
  136.          * 0 rgb rgb rgb ... rgb
  137.          * 1 rgb rgb rgb ... rgb
  138.          * 1. LCDSADDR1:
  139.          * 设置LCDBANK、LCDBASEU
  140.          * 2. LCDSADDR2:
  141.          * 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
  142.          * 3. LCDSADDR3:
  143.          * OFFSIZE等于0,PAGEWIDTH等于(240*2/2)
  144.          */
  145.         LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
  146.         LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
  147.                     (LINEVAL_TFT_240320+1)*(HOZVAL_TFT_240320+1)*2)>>1);
  148.         LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_240320*2/2);

  149.         /* 禁止临时调色板寄存器 */
  150.         TPAL = 0;

  151.         fb_base_addr = LCDFRAMEBUFFER;
  152.         bpp = 16;
  153.         xsize = 240;
  154.         ysize = 320;

  155.         break;
  156.         
  157.     case MODE_TFT_8BIT_640480:
  158.         /*
  159.          * 设置LCD控制器的控制寄存器LCDCON1~5
  160.          * 1. LCDCON1:
  161.          * 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
  162.          * 选择LCD类型: TFT LCD
  163.          * 设置显示模式: 8BPP
  164.          * 先禁止LCD信号输出
  165.          * 2. LCDCON2/3/4:
  166.          * 设置控制信号的时间参数
  167.          * 设置分辨率,即行数及列数
  168.          * 现在,可以根据公式计算出显示器的频率:
  169.          * 当HCLK=100MHz时,
  170.          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
  171.          * {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
  172.          * {2x(CLKVAL+1)/(HCLK)}]
  173.          * = 60Hz
  174.          * 3. LCDCON5:
  175.          * 设置显示模式为8BPP时,调色板中的数据格式: 5:6:5
  176.          * 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
  177.          * 字节交换使能
  178.          */
  179.         LCDCON1 = (CLKVAL_TFT_640480<<8) | (LCDTYPE_TFT<<5) | \
  180.                   (BPPMODE_8BPP<<1) | (ENVID_DISABLE<<0);
  181.         LCDCON2 = (VBPD_640480<<24) | (LINEVAL_TFT_640480<<14) | \
  182.                   (VFPD_640480<<6) | (VSPW_640480);
  183.         LCDCON3 = (HBPD_640480<<19) | (HOZVAL_TFT_640480<<8) | (HFPD_640480);
  184.         LCDCON4 = HSPW_640480;
  185.         LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
  186.                   (BSWP<<1);

  187.         /*
  188.          * 设置LCD控制器的地址寄存器LCDSADDR1~3
  189.          * 帧内存与视口(view point)完全吻合,
  190.          * 图像数据格式如下(8BPP时,帧缓冲区中的数据为调色板中的索引值):
  191.          * |----PAGEWIDTH----|
  192.          * y/x 0 1 2 639
  193.          * 0 idx idx idx ... idx
  194.          * 1 idx idx idx ... idx
  195.          * 1. LCDSADDR1:
  196.          * 设置LCDBANK、LCDBASEU
  197.          * 2. LCDSADDR2:
  198.          * 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
  199.          * 3. LCDSADDR3:
  200.          * OFFSIZE等于0,PAGEWIDTH等于(640/2)
  201.          */
  202.         LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
  203.         LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
  204.                     (LINEVAL_TFT_640480+1)*(HOZVAL_TFT_640480+1)*1)>>1);
  205.         LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480/2);

  206.         /* 禁止临时调色板寄存器 */
  207.         TPAL = 0;

  208.         fb_base_addr = LCDFRAMEBUFFER;
  209.         bpp = 8;
  210.         xsize = 640;
  211.         ysize = 480;
  212.         
  213.         break;
  214.         
  215.     case MODE_TFT_16BIT_640480:
  216.         /*
  217.          * 设置LCD控制器的控制寄存器LCDCON1~5
  218.          * 1. LCDCON1:
  219.          * 设置VCLK的频率:VCLK(Hz) = HCLK/[(CLKVAL+1)x2]
  220.          * 选择LCD类型: TFT LCD
  221.          * 设置显示模式: 16BPP
  222.          * 先禁止LCD信号输出
  223.          * 2. LCDCON2/3/4:
  224.          * 设置控制信号的时间参数
  225.          * 设置分辨率,即行数及列数
  226.          * 现在,可以根据公式计算出显示器的频率:
  227.          * 当HCLK=100MHz时,
  228.          * Frame Rate = 1/[{(VSPW+1)+(VBPD+1)+(LIINEVAL+1)+(VFPD+1)}x
  229.          * {(HSPW+1)+(HBPD+1)+(HFPD+1)+(HOZVAL+1)}x
  230.          * {2x(CLKVAL+1)/(HCLK)}]
  231.          * = 60Hz
  232.          * 3. LCDCON5:
  233.          * 设置显示模式为16BPP时的数据格式: 5:6:5
  234.          * 设置HSYNC、VSYNC脉冲的极性(这需要参考具体LCD的接口信号): 反转
  235.          * 半字(2字节)交换使能
  236.          */
  237.         LCDCON1 = (CLKVAL_TFT_640480<<8) | (LCDTYPE_TFT<<5) | \
  238.                   (BPPMODE_16BPP<<1) | (ENVID_DISABLE<<0);
  239.         LCDCON2 = (VBPD_640480<<24) | (LINEVAL_TFT_640480<<14) | \
  240.                   (VFPD_640480<<6) | (VSPW_640480);
  241.         LCDCON3 = (HBPD_640480<<19) | (HOZVAL_TFT_640480<<8) | (HFPD_640480);
  242.         LCDCON4 = HSPW_640480;
  243.         LCDCON5 = (FORMAT8BPP_565<<11) | (HSYNC_INV<<9) | (VSYNC_INV<<8) | \
  244.                   (HWSWP<<1);

  245.         /*
  246.          * 设置LCD控制器的地址寄存器LCDSADDR1~3
  247.          * 帧内存与视口(view point)完全吻合,
  248.          * 图像数据格式如下:
  249.          * |----PAGEWIDTH----|
  250.          * y/x 0 1 2 639
  251.          * 0 rgb rgb rgb ... rgb
  252.          * 1 rgb rgb rgb ... rgb
  253.          * 1. LCDSADDR1:
  254.          * 设置LCDBANK、LCDBASEU
  255.          * 2. LCDSADDR2:
  256.          * 设置LCDBASEL: 帧缓冲区的结束地址A[21:1]
  257.          * 3. LCDSADDR3:
  258.          * OFFSIZE等于0,PAGEWIDTH等于(640*2/2)
  259.          */
  260.         LCDSADDR1 = ((LCDFRAMEBUFFER>>22)<<21) | LOWER21BITS(LCDFRAMEBUFFER>>1);
  261.         LCDSADDR2 = LOWER21BITS((LCDFRAMEBUFFER+ \
  262.                     (LINEVAL_TFT_640480+1)*(HOZVAL_TFT_640480+1)*2)>>1);
  263.         LCDSADDR3 = (0<<11) | (LCD_XSIZE_TFT_640480*2/2);

  264.         /* 禁止临时调色板寄存器 */
  265.         TPAL = 0;

  266.         fb_base_addr = LCDFRAMEBUFFER;
  267.         bpp = 16;
  268.         xsize = 640;
  269.         ysize = 480;

  270.         break;

  271.     default:
  272.         break;
  273.     }
  274. }

  275. /*
  276.  * 设置调色板
  277.  */
  278. void Lcd_Palette8Bit_Init(void)
  279. {
  280.     int i;
  281.     volatile unsigned int *palette;
  282.     
  283.     LCDCON5 |= (FORMAT8BPP_565<<11); // 设置调色板中数据格式为5:6:5
  284.     palette = (volatile unsigned int *)PALETTE;
  285.     for (i = 0; i < 256; i++)
  286.         *palette++ = DEMO256pal[i];
  287. }

  288. /*
  289.  * 改变调色板为一种颜色
  290.  * 输入参数:
  291.  * color: 颜色值,格式为0xRRGGBB
  292.  */
  293. void ChangePalette(UINT32 color)
  294. {
  295.     int i;
  296.     unsigned char red, green, blue;
  297.     UINT32 *palette;
  298.     
  299.     palette=(UINT32 *)PALETTE;
  300.     for (i = 0; i < 256; i++)
  301.     {
  302.         red = (color >> 19) & 0xff;
  303.         green = (color >> 10) & 0xff;
  304.         blue = (color >> 3) & 0xff;
  305.         color = (red << 11) | (green << 5) | blue; // 格式5:6:5

  306.         while ((LCDCON5>>16) == 2); // 等待直到VSTATUS不为”有效”

  307.         *palette++ = color;
  308.     }
  309. }

  310. /*
  311.  * 设置是否输出LCD电源开关信号LCD_PWREN
  312.  * 输入参数:
  313.  * invpwren: 0 - LCD_PWREN有效时为正常极性
  314.  * 1 - LCD_PWREN有效时为反转极性
  315.  * pwren: 0 - LCD_PWREN输出有效
  316.  * 1 - LCD_PWREN输出无效
  317.  */
  318. void Lcd_PowerEnable(int invpwren, int pwren)
  319. {
  320.     GPGCON = (GPGCON & (~(3<<8))) | (3<<8); // GPG4用作LCD_PWREN

  321.     GPGUP = (GPGUP & (~(1<<4))) | (1<<4); // 禁止内部上拉
  322.    
  323.     LCDCON5 = (LCDCON5 & (~(1<<5))) | (invpwren<<5); // 设置LCD_PWREN的极性: 正常/反转

  324.     LCDCON5 = (LCDCON5 & (~(1<<3))) | (pwren<<3); // 设置是否输出LCD_PWREN

  325. }

  326. /*
  327.  * 设置LCD控制器是否输出信号
  328.  * 输入参数:
  329.  * onoff:
  330.  * 0 : 关闭
  331.  * 1 : 打开
  332.  */
  333. void Lcd_EnvidOnOff(int onoff)
  334. {
  335.     if (onoff == 1)
  336.         LCDCON1 |= 1; // ENVID ON
  337.     else
  338.         LCDCON1 &= 0x3fffe; // ENVID Off

  339. }

  340. /*
  341.  * 使用临时调色板寄存器输出单色图像
  342.  * 输入参数:
  343.  * color: 颜色值,格式为0xRRGGBB
  344.  */
  345. void ClearScrWithTmpPlt(UINT32 color)
  346. {
  347.     TPAL = (1<<24)|((color & 0xffffff)<<0);
  348. }

  349. /*
  350.  * 停止使用临时调色板寄存器
  351.  */
  352. void DisableTmpPlt(void)
  353. {
  354.     TPAL = 0;
  355. }

framebuffer.c  //绘制像素点,直线,圆

  1. /*
  2.  * FILE: framebuffer.c
  3.  * 实现在framebuffer上画点、画线、画同心圆、清屏的函数
  4.  */

  5. #include "framebuffer.h"

  6. extern unsigned int fb_base_addr;
  7. extern unsigned int bpp;
  8. extern unsigned int xsize;
  9. extern unsigned int ysize;

  10. /*
  11.  * 画点
  12.  * 输入参数:
  13.  * x、y : 象素坐标
  14.  * color: 颜色值
  15.  * 对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
  16.  * 需要转换为5:6:5格式
  17.  * 对于8BPP: color为调色板中的索引值,
  18.  * 其颜色取决于调色板中的数值
  19.  */
  20. void PutPixel(UINT32 x, UINT32 y, UINT32 color)
  21. {
  22.     UINT8 red,green,blue;

  23.     switch (bpp){
  24.         case 16:
  25.         {
  26.             UINT16 *addr = (UINT16 *)fb_base_addr + (y * xsize + x);
  27.             red = (color >> 19) & 0xff;
  28.             green = (color >> 10) & 0xff;
  29.             blue = (color >> 3) & 0xff;
  30.             color = (red << 11) | (green << 5) | blue; // 格式5:6:5

  31.             *addr = (UINT16) color;
  32.             break;
  33.         }
  34.         
  35.         case 8:
  36.         {
  37.             UINT8 *addr = (UINT8 *)fb_base_addr + (y * xsize + x);
  38.             *addr = (UINT8) color;
  39.             break;
  40.         }

  41.         default:
  42.             break;
  43.     }
  44. }

  45. /*
  46.  * 画线
  47.  * 输入参数:
  48.  * x1、y1 : 起点坐标
  49.  * x2、y2 : 终点坐标
  50.  * color : 颜色值
  51.  * 对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
  52.  * 需要转换为5:6:5格式
  53.  * 对于8BPP: color为调色板中的索引值,
  54.  * 其颜色取决于调色板中的数值
  55.  */
  56. void DrawLine(int x1,int y1,int x2,int y2,int color)
  57. {
  58.     int dx,dy,e;
  59.     dx=x2-x1;
  60.     dy=y2-y1;
  61.     
  62.     if(dx>=0)
  63.     {
  64.         if(dy >= 0) // dy>=0

  65.         {
  66.             if(dx>=dy) // 1/8 octant

  67.             {
  68.                 e=dy-dx/2;
  69.                 while(x1<=x2)
  70.                 {
  71.                     PutPixel(x1,y1,color);
  72.                     if(e>0){y1+=1;e-=dx;}
  73.                     x1+=1;
  74.                     e+=dy;
  75.                 }
  76.             }
  77.             else // 2/8 octant

  78.             {
  79.                 e=dx-dy/2;
  80.                 while(y1<=y2)
  81.                 {
  82.                     PutPixel(x1,y1,color);
  83.                     if(e>0){x1+=1;e-=dy;}
  84.                     y1+=1;
  85.                     e+=dx;
  86.                 }
  87.             }
  88.         }
  89.         else // dy<0

  90.         {
  91.             dy=-dy; // dy=abs(dy)


  92.             if(dx>=dy) // 8/8 octant

  93.             {
  94.                 e=dy-dx/2;
  95.                 while(x1<=x2)
  96.                 {
  97.                     PutPixel(x1,y1,color);
  98.                     if(e>0){y1-=1;e-=dx;}
  99.                     x1+=1;
  100.                     e+=dy;
  101.                 }
  102.             }
  103.             else // 7/8 octant

  104.             {
  105.                 e=dx-dy/2;
  106.                 while(y1>=y2)
  107.                 {
  108.                     PutPixel(x1,y1,color);
  109.                     if(e>0){x1+=1;e-=dy;}
  110.                     y1-=1;
  111.                     e+=dx;
  112.                 }
  113.             }
  114.         }
  115.     }
  116.     else //dx<0

  117.     {
  118.         dx=-dx; //dx=abs(dx)

  119.         if(dy >= 0) // dy>=0

  120.         {
  121.             if(dx>=dy) // 4/8 octant

  122.             {
  123.                 e=dy-dx/2;
  124.                 while(x1>=x2)
  125.                 {
  126.                     PutPixel(x1,y1,color);
  127.                     if(e>0){y1+=1;e-=dx;}
  128.                     x1-=1;
  129.                     e+=dy;
  130.                 }
  131.             }
  132.             else // 3/8 octant

  133.             {
  134.                 e=dx-dy/2;
  135.                 while(y1<=y2)
  136.                 {
  137.                     PutPixel(x1,y1,color);
  138.                     if(e>0){x1-=1;e-=dy;}
  139.                     y1+=1;
  140.                     e+=dx;
  141.                 }
  142.             }
  143.         }
  144.         else // dy<0

  145.         {
  146.             dy=-dy; // dy=abs(dy)


  147.             if(dx>=dy) // 5/8 octant

  148.             {
  149.                 e=dy-dx/2;
  150.                 while(x1>=x2)
  151.                 {
  152.                     PutPixel(x1,y1,color);
  153.                     if(e>0){y1-=1;e-=dx;}
  154.                     x1-=1;
  155.                     e+=dy;
  156.                 }
  157.             }
  158.             else // 6/8 octant

  159.             {
  160.                 e=dx-dy/2;
  161.                 while(y1>=y2)
  162.                 {
  163.                     PutPixel(x1,y1,color);
  164.                     if(e>0){x1-=1;e-=dy;}
  165.                     y1-=1;
  166.                     e+=dx;
  167.                 }
  168.             }
  169.         }
  170.     }
  171. }

  172. /*
  173.  * 绘制同心圆
  174.  */
  175. void Mire(void)
  176. {
  177.     UINT32 x,y;
  178.     UINT32 color;
  179.     UINT8 red,green,blue,alpha;

  180.     for (y = 0; y < ysize; y++)
  181.         for (x = 0; x < xsize; x++){
  182.             color = ((x-xsize/2)*(x-xsize/2) + (y-ysize/2)*(y-ysize/2))/64;
  183.             red = (color/8) % 256;
  184.             green = (color/4) % 256;
  185.             blue = (color/2) % 256;
  186.             alpha = (color*2) % 256;

  187.             color |= ((UINT32)alpha << 24);
  188.             color |= ((UINT32)red << 16);
  189.             color |= ((UINT32)green << 8 );
  190.             color |= ((UINT32)blue );

  191.             PutPixel(x,y,color);
  192.         }
  193. }

  194. /*
  195.  * 将屏幕清成单色
  196.  * 输入参数:
  197.  * color: 颜色值
  198.  * 对于16BPP: color的格式为0xAARRGGBB (AA = 透明度),
  199.  * 需要转换为5:6:5格式
  200.  * 对于8BPP: color为调色板中的索引值,
  201.  * 其颜色取决于调色板中的数值
  202.  */
  203. void ClearScr(UINT32 color)
  204. {
  205.     UINT32 x,y;
  206.     
  207.     for (y = 0; y < ysize; y++)
  208.         for (x = 0; x < xsize; x++)
  209.             PutPixel(x, y, color);
  210. }

lcdlib.c  //LCD测试

 

  1. /*
  2.  * FILE: lcdlib.c
  3.  * 实现TFT LCD的测试函数
  4.  */

  5. #include <stdio.h>
  6. #include "lcddrv.h"
  7. #include "framebuffer.h"


  8. /*
  9.  * 以240x320,8bpp的显示模式测试TFT LCD
  10.  */
  11. void Test_Lcd_Tft_8Bit_240320(void)
  12. {
  13.     Lcd_Port_Init(); // 设置LCD引脚

  14.     Tft_Lcd_Init(MODE_TFT_8BIT_240320); // 初始化LCD控制器

  15.     Lcd_PowerEnable(0, 1); // 设置LCD_PWREN有效,它用于打开LCD的电源

  16.     Lcd_EnvidOnOff(1); // 使能LCD控制器输出信号


  17.     Lcd_Palette8Bit_Init(); // 初始化调色板

  18.     ClearScr(0x0); // 清屏

  19.     printf("\n\r[TFT 64K COLOR(16bpp) LCD TEST]\n\r");

  20.     printf("1. Press any key to draw line\n");
  21.     getc();
  22.     DrawLine(0 , 0 , 239, 0 , 0); // 颜色为DEMO256pal[0]

  23.     DrawLine(0 , 0 , 0 , 239, 1); // 颜色为DEMO256pal[1]

  24.     DrawLine(239, 0 , 239, 319, 2); // ……

  25.     DrawLine(0 , 319, 239, 319, 4);
  26.     DrawLine(0 , 0 , 239, 319, 8);
  27.     DrawLine(239, 0 , 0 , 319, 16);
  28.     DrawLine(120, 0 , 120, 319, 32);
  29.     DrawLine(0 , 160, 239, 160, 64);

  30.     printf("2. Press any key to draw circles\n");
  31.     getc();
  32.     Mire();

  33.     printf("3. Press any key to fill the screem with one color\n");
  34.     getc();
  35.     ClearScr(128); // 输出单色图像,颜色为DEMO256pal[128]


  36.     printf("4. Press any key to fill the screem by temporary palette\n");
  37.     getc();
  38.     ClearScrWithTmpPlt(0x0000ff); // 输出单色图像,颜色为蓝色


  39.     printf("5. Press any key to fill the screem by palette\n");
  40.     getc();
  41.     DisableTmpPlt(); // 关闭临时调色板寄存器

  42.     ChangePalette(0xffff00); // 改变整个调色板为黄色,输出单色图像

  43.     
  44.     printf("6. Press any key stop the testing\n");
  45.     getc();
  46.     Lcd_EnvidOnOff(0);
  47. }

  48. /*
  49.  * 以240x320,16bpp的显示模式测试TFT LCD
  50.  */
  51. void Test_Lcd_Tft_16Bit_240320(void)
  52. {
  53.     Lcd_Port_Init(); // 设置LCD引脚

  54.     Tft_Lcd_Init(MODE_TFT_16BIT_240320); // 初始化LCD控制器

  55.     Lcd_PowerEnable(0, 1); // 设置LCD_PWREN有效,它用于打开LCD的电源

  56.     Lcd_EnvidOnOff(1); // 使能LCD控制器输出信号


  57.     ClearScr(0x0); // 清屏,黑色

  58.     printf("\n\r[TFT 64K COLOR(16bpp) LCD TEST]\n\r");

  59.     printf("1. Press any key to draw line\n");
  60.     getc();
  61.     DrawLine(0 , 0 , 239, 0 , 0xff0000); // 绿色

  62.     DrawLine(0 , 0 , 0 , 319, 0x00ff00); // 红色

  63.     DrawLine(239, 0 , 239, 319, 0x0000ff); // 蓝色

  64.     DrawLine(0 , 319, 239, 319, 0xffffff); // 白色

  65.     DrawLine(0 , 0 , 239, 319, 0xffff00); // 黄色

  66.     DrawLine(239, 0 , 0 , 319, 0x8000ff); // 紫色

  67.     DrawLine(120, 0 , 120, 319, 0xe6e8fa); // 银色

  68.     DrawLine(0 , 160, 239, 160, 0xcd7f32); // 金色


  69.     printf("2. Press any key to draw circles\n");
  70.     getc();
  71.     Mire();

  72.     printf("3. Press any key to fill the screem with one color\n");
  73.     getc();
  74.     ClearScr(0xff0000); // 红色


  75.     printf("4. Press any key to fill the screem by temporary palette\n");
  76.     getc();
  77.     ClearScrWithTmpPlt(0x0000ff); // 蓝色


  78.     printf("5. Press any key stop the testing\n");
  79.     getc();
  80.     Lcd_EnvidOnOff(0);
  81. }


  82. /*
  83.  * 以640x480,8bpp的显示模式测试TFT LCD
  84.  */
  85. void Test_Lcd_Tft_8Bit_640480(void)
  86. {
  87.     Lcd_Port_Init(); // 设置LCD引脚

  88.     Tft_Lcd_Init(MODE_TFT_8BIT_640480); // 初始化LCD控制器

  89.     Lcd_PowerEnable(0, 1); // 设置LCD_PWREN有效,它用于打开LCD的电源

  90.     Lcd_EnvidOnOff(1); // 使能LCD控制器输出信号


  91.     Lcd_Palette8Bit_Init(); // 初始化调色板

  92.     ClearScr(0x0); // 清屏,黑色

  93.     printf("[TFT 64K COLOR(16bpp) LCD TEST]\n");

  94.     printf("1. Press any key to draw line\n");
  95.     getc();
  96.     DrawLine(0 , 0 , 639, 0 , 0); // 颜色为DEMO256pal[0]

  97.     DrawLine(0 , 0 , 0 , 479, 1); // 颜色为DEMO256pal[1]

  98.     DrawLine(639, 0 , 639, 479, 2); // ……

  99.     DrawLine(0 , 479, 639, 479, 4);
  100.     DrawLine(0 , 0 , 639, 479, 8);
  101.     DrawLine(639, 0 , 0 , 479, 16);
  102.     DrawLine(320, 0 , 320, 479, 32);
  103.     DrawLine(0 , 240, 639, 240, 64);

  104.     printf("2. Press any key to draw circles\n");
  105.     getc();
  106.     Mire();

  107.     printf("3. Press any key to fill the screem with one color\n");
  108.     getc();
  109.     ClearScr(128); // 输出单色图像,颜色为DEMO256pal[128]


  110.     printf("4. Press any key to fill the screem by temporary palette\n");
  111.     getc();
  112.     ClearScrWithTmpPlt(0x0000ff); // 输出单色图像,颜色为蓝色

  113.     
  114.     printf("5. Press any key to fill the screem by palette\n");
  115.     getc();
  116.     DisableTmpPlt(); // 关闭临时调色板寄存器

  117.     ChangePalette(0xffff00); // 改变整个调色板为黄色,输出单色图像

  118.     
  119.     printf("6. Press any key stop the testing\n");
  120.     getc();
  121.     Lcd_EnvidOnOff(0);
  122. }

  123. /*
  124.  * 以640x480,16bpp的显示模式测试TFT LCD
  125.  */
  126. void Test_Lcd_Tft_16Bit_640480(void)
  127. {
  128.     Lcd_Port_Init(); // 设置LCD引脚

  129.     Tft_Lcd_Init(MODE_TFT_16BIT_640480); // 初始化LCD控制器

  130.     Lcd_PowerEnable(0, 1); // 设置LCD_PWREN有效,它用于打开LCD的电源

  131.     Lcd_EnvidOnOff(1); // 使能LCD控制器输出信号


  132.     ClearScr(0x0); // 清屏,黑色

  133.     printf("[TFT 64K COLOR(16bpp) LCD TEST]\n");

  134.     printf("1. Press any key to draw line\n");
  135.     getc();
  136.     DrawLine(0 , 0 , 639, 0 , 0xff0000); // 红色

  137.     DrawLine(0 , 0 , 0 , 479, 0x00ff00); // 绿色

  138.     DrawLine(639, 0 , 639, 479, 0x0000ff); // 蓝色

  139.     DrawLine(0 , 479, 639, 479, 0xffffff); // 白色

  140.     DrawLine(0 , 0 , 639, 479, 0xffff00); // 黄色

  141.     DrawLine(639, 0 , 0 , 479, 0x8000ff); // 紫色

  142.     DrawLine(320, 0 , 320, 479, 0xe6e8fa); // 银色

  143.     DrawLine(0 , 240, 639, 240, 0xcd7f32); // 金色


  144.     printf("2. Press any key to draw circles\n");
  145.     getc();
  146.     Mire();

  147.     printf("3. Press any key to fill the screem with one color\n");
  148.     getc();
  149.     ClearScr(0xff0000); // 红色


  150.     printf("4. Press any key to fill the screem by temporary palette\n");
  151.     getc();
  152.     ClearScrWithTmpPlt(0x0000ff); // 蓝色


  153.     printf("5. Press any key stop the testing\n");
  154.     getc();
  155.     Lcd_EnvidOnOff(0);
  156. }

十、运行效果图

以下为能直接运行的二进制文件,下载到Nand Flash Black0 直接以Nand Flash运行。

 

 

阅读(1961) | 评论(0) | 转发(0) |
0

上一篇:Makefile模板

下一篇:15、ADC和触摸屏-S3C2440

给主人留下些什么吧!~~