在前面的博客中,使用的像素格式都是16bpp,24bpp(24bpp实际实际上就是32bpp)?如果想使用8bpp时,就需要使用调色板。
在以前的博客中,曾经说过,在framebuffer中如果每个像素用8bpp表示,这8bpp怎么转换成lcd需要的16bpp的数据,需要引入一个调色板。
2的8次方,为256。即调色板中有256项,0-255。需要在调色板所对应的内存里面,填入16bpp的数据(这些数据就是真正的颜色值)。把lcd控制器设置为8bpp时,它会从framebuffer中取出一个像素的数据(8位),使用这8位数据作为一个索引,在调色板中取出真正的颜色,从而就得到了16位的数据。最终将这16位的数据发给lcd。
需要修改s3c2440_lcd_controller.c lcd_controller.c中的代码:
1 #include "lcd.h" 2 #include "lcd_controller.h" 3 #include "../s3c2440_soc.h" 4 5 #define HCLK 100 6 7 void jz2440_lcd_pin_init(void) 8 { 9 /* 初始化引脚 : 背光引脚 */ 10 GPBCON &= ~0x3; 11 GPBCON |= 0x01; 12 13 /* LCD专用引脚 */ 14 GPCCON = 0xaaaaaaaa; 15 GPDCON = 0xaaaaaaaa; 16 17 /* PWREN */ 18 GPGCON |= (3<<8); 19 } 20 21 22 /* 根据传入的LCD参数设置LCD控制器 */ 23 void s3c2440_lcd_controller_init(p_lcd_params plcdparams) 24 { 25 int pixelplace; 26 unsigned int addr; 27 28 jz2440_lcd_pin_init(); 29 30 /* [17:8]: clkval, vclk = HCLK / [(CLKVAL+1) x 2] 31 * 9 = 100M /[(CLKVAL+1) x 2], clkval = 4.5 = 5 32 * CLKVAL = 100/vclk/2-1 33 * [6:5]: 0b11, tft lcd 34 * [4:1]: bpp mode 35 * [0] : LCD video output and the logic enable/disable 36 */ 37 int clkval = (float)HCLK/plcdparams->time_seq.vclk/2-1+0.5; 38 //int clkval = 5; 39 int bppmode = plcdparams->bpp == 8 ? 0xb :\ 40 plcdparams->bpp == 16 ? 0xc :\ 41 0xd; /* 0xd: 24,32bpp */ 42 LCDCON1 = (clkval<<8) | (3<<5) | (bppmode<<1) ; 43 44 /* [31:24] : VBPD = tvb - 1 45 * [23:14] : LINEVAL = line - 1 46 * [13:6] : VFPD = tvf - 1 47 * [5:0] : VSPW = tvp - 1 48 */ 49 LCDCON2 = ((plcdparams->time_seq.tvb - 1)<<24) | \ 50 ((plcdparams->yres - 1)<<14) | \ 51 ((plcdparams->time_seq.tvf - 1)<<6) | \ 52 ((plcdparams->time_seq.tvp - 1)<<0); 53 54 /* [25:19] : HBPD = thb - 1 55 * [18:8] : HOZVAL = 列 - 1 56 * [7:0] : HFPD = thf - 1 57 */ 58 LCDCON3 = ((plcdparams->time_seq.thb - 1)<<19) | \ 59 ((plcdparams->xres - 1)<<8) | \ 60 ((plcdparams->time_seq.thf - 1)<<0); 61 62 /* 63 * [7:0] : HSPW = thp - 1 64 */ 65 LCDCON4 = ((plcdparams->time_seq.thp - 1)<<0); 66 67 /* 用来设置引脚极性, 设置16bpp, 设置内存中象素存放的格式 68 * [12] : BPP24BL 69 * [11] : FRM565, 1-565 70 * [10] : INVVCLK, 0 = The video data is fetched at VCLK falling edge 71 * [9] : HSYNC是否反转 72 * [8] : VSYNC是否反转 73 * [7] : INVVD, rgb是否反转 74 * [6] : INVVDEN 75 * [5] : INVPWREN 76 * [4] : INVLEND 77 * [3] : PWREN, LCD_PWREN output signal enable/disable 78 * [2] : ENLEND 79 * [1] : BSWP 80 * [0] : HWSWP 81 */ 82 83 pixelplace = plcdparams->bpp == 32 ? (0) : \ 84 plcdparams->bpp == 16 ? (1) : \ 85 (1<<1); /* 8bpp */ 86 87 LCDCON5 = (plcdparams->pins_pol.vclk<<10) |\ 88 (plcdparams->pins_pol.rgb<<7) |\ 89 (plcdparams->pins_pol.hsync<<9) |\ 90 (plcdparams->pins_pol.vsync<<8) |\ 91 (plcdparams->pins_pol.de<<6) |\ 92 (plcdparams->pins_pol.pwren<<5) |\ 93 (1<<11) | pixelplace; 94 95 /* framebuffer地址 */ 96 /* 97 * [29:21] : LCDBANK, A[30:22] of fb 98 * [20:0] : LCDBASEU, A[21:1] of fb 99 */ 100 addr = plcdparams->fb_base & ~(1<<31); 101 LCDSADDR1 = (addr >> 1); 102 103 /* 104 * [20:0] : LCDBASEL, A[21:1] of end addr 105 */ 106 addr = plcdparams->fb_base + plcdparams->xres*plcdparams->yres*plcdparams->bpp/8; 107 addr >>=1; 108 addr &= 0x1fffff; 109 LCDSADDR2 = addr;// 110 } 111 112 void s3c2440_lcd_controller_enalbe(void) 113 { 114 /* 背光引脚 : GPB0 */ 115 GPBDAT |= (1<<0); 116 117 /* pwren : 给LCD提供AVDD */ 118 LCDCON5 |= (1<<3); 119 120 /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */ 121 LCDCON1 |= (1<<0); 122 } 123 124 void s3c2440_lcd_controller_disable(void) 125 { 126 /* 背光引脚 : GPB0 */ 127 GPBDAT &= ~(1<<0); 128 129 /* pwren : 给LCD提供AVDD */ 130 LCDCON5 &= ~(1<<3); 131 132 /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */ 133 LCDCON1 &= ~(1<<0); 134 } 135 136 137 /* 设置调色板之前, 先关闭lcd_controller */ 138 void s3c2440_lcd_controller_init_palette(void) 139 { 140 volatile unsigned int *palette_base = (volatile unsigned int *)0x4D000400; 141 int i; 142 143 int bit = LCDCON1 & (1<<0); 144 145 /* LCDCON1'BIT 0 : 设置LCD控制器是否输出信号 */ 146 if (bit) 147 LCDCON1 &= ~(1<<0); 148 149 for (i = 0; i < 256; i++) 150 { 151 /* 低16位 : rgb565 */ 152 *palette_base++ = i; 153 } 154 155 if (bit) 156 LCDCON1 |= (1<<0); 157 } 158 159 struct lcd_controller s3c2440_lcd_controller = { 160 .name = "s3c2440", 161 .init = s3c2440_lcd_controller_init, 162 .enable = s3c2440_lcd_controller_enalbe, 163 .disable = s3c2440_lcd_controller_disable, 164 .init_palette = s3c2440_lcd_controller_init_palette, 165 }; 166 167 168 void s3c2440_lcd_contoller_add(void) 169 { 170 register_lcd_controller(&s3c2440_lcd_controller); 171 }
1 #include "lcd_controller.h" 2 3 #define LCD_CONTROLLER_NUM 10 4 5 static p_lcd_controller p_array_lcd_controller[LCD_CONTROLLER_NUM]; 6 static p_lcd_controller g_p_lcd_controller_selected; 7 8 int register_lcd_controller(p_lcd_controller plcdcon) 9 { 10 int i; 11 for (i = 0; i < LCD_CONTROLLER_NUM; i++) 12 { 13 if (!p_array_lcd_controller[i]) 14 { 15 p_array_lcd_controller[i] = plcdcon; 16 return i; 17 } 18 } 19 return -1; 20 } 21 22 int select_lcd_controller(char *name) 23 { 24 int i; 25 for (i = 0; i < LCD_CONTROLLER_NUM; i++) 26 { 27 if (p_array_lcd_controller[i] && !strcmp(p_array_lcd_controller[i]->name, name)) 28 { 29 g_p_lcd_controller_selected = p_array_lcd_controller[i]; 30 return i; 31 } 32 } 33 return -1; 34 } 35 36 37 /* 向上: 接收不同LCD的参数 38 * 向下: 使用这些参数设置对应的LCD控制器 39 */ 40 41 int lcd_controller_init(p_lcd_params plcdparams) 42 { 43 /* 调用所选择的LCD控制器的初始化函数 */ 44 if (g_p_lcd_controller_selected) 45 { 46 g_p_lcd_controller_selected->init(plcdparams); 47 g_p_lcd_controller_selected->init_palette(); 48 return 0; 49 } 50 return -1; 51 } 52 53 void lcd_controller_enable(void) 54 { 55 if (g_p_lcd_controller_selected) 56 { 57 g_p_lcd_controller_selected->enable(); 58 } 59 } 60 61 void lcd_controller_disable(void) 62 { 63 if (g_p_lcd_controller_selected) 64 { 65 g_p_lcd_controller_selected->disable(); 66 } 67 } 68 69 70 void lcd_contoller_add(void) 71 { 72 s3c2440_lcd_contoller_add(); 73 }
再来看一下,lcd_4.3中,做了什么修改?
led_test.c,注意:这里面的颜色值都是随便写的。目的就是想看看,使用8bpp时,能够实现功能。
1 #include "geometry.h" 2 #include "font.h" 3 4 void lcd_test(void) 5 { 6 unsigned int fb_base; 7 int xres, yres, bpp; 8 int x, y; 9 unsigned char *p0; 10 unsigned short *p; 11 unsigned int *p2; 12 13 /* 初始化LCD */ 14 lcd_init(); 15 16 /* 使能LCD */ 17 lcd_enable(); 18 19 /* 获得LCD的参数: fb_base, xres, yres, bpp */ 20 get_lcd_params(&fb_base, &xres, &yres, &bpp); 21 fb_get_lcd_params(); 22 font_init(); 23 24 /* 往framebuffer中写数据 */ 25 if (bpp == 8) 26 { 27 /* 让LCD输出整屏的红色 */ 28 29 /* bpp: palette[12] */ 30 31 p0 = (unsigned char *)fb_base; 32 for (x = 0; x < xres; x++) 33 for (y = 0; y < yres; y++) 34 *p0++ = 12; 35 36 /* palette[47] */ 37 p0 = (unsigned char *)fb_base; 38 for (x = 0; x < xres; x++) 39 for (y = 0; y < yres; y++) 40 *p0++ = 47; 41 42 /* palette[88] */ 43 p0 = (unsigned char *)fb_base; 44 for (x = 0; x < xres; x++) 45 for (y = 0; y < yres; y++) 46 *p0++ = 88; 47 48 /* palette[0] */ 49 p0 = (unsigned char *)fb_base; 50 for (x = 0; x < xres; x++) 51 for (y = 0; y < yres; y++) 52 *p0++ = 0; 53 54 } 55 else if (bpp == 16) 56 { 57 /* 让LCD输出整屏的红色 */ 58 59 /* 565: 0xf800 */ 60 61 p = (unsigned short *)fb_base; 62 for (x = 0; x < xres; x++) 63 for (y = 0; y < yres; y++) 64 *p++ = 0xf800; 65 66 /* green */ 67 p = (unsigned short *)fb_base; 68 for (x = 0; x < xres; x++) 69 for (y = 0; y < yres; y++) 70 *p++ = 0x7e0; 71 72 /* blue */ 73 p = (unsigned short *)fb_base; 74 for (x = 0; x < xres; x++) 75 for (y = 0; y < yres; y++) 76 *p++ = 0x1f; 77 78 /* black */ 79 p = (unsigned short *)fb_base; 80 for (x = 0; x < xres; x++) 81 for (y = 0; y < yres; y++) 82 *p++ = 0; 83 84 } 85 else if (bpp == 32) 86 { 87 /* 让LCD输出整屏的红色 */ 88 89 /* 0xRRGGBB */ 90 91 p2 = (unsigned int *)fb_base; 92 for (x = 0; x < xres; x++) 93 for (y = 0; y < yres; y++) 94 *p2++ = 0xff0000; 95 96 /* green */ 97 p2 = (unsigned int *)fb_base; 98 for (x = 0; x < xres; x++) 99 for (y = 0; y < yres; y++) 100 *p2++ = 0x00ff00; 101 102 /* blue */ 103 p2 = (unsigned int *)fb_base; 104 for (x = 0; x < xres; x++) 105 for (y = 0; y < yres; y++) 106 *p2++ = 0x0000ff; 107 108 /* black */ 109 p2 = (unsigned int *)fb_base; 110 for (x = 0; x < xres; x++) 111 for (y = 0; y < yres; y++) 112 *p2++ = 0; 113 114 } 115 116 delay(1000000); 117 118 /* 画线 */ 119 draw_line(0, 0, xres - 1, 0, 0x23ff77); 120 draw_line(xres - 1, 0, xres - 1, yres - 1, 0xffff); 121 draw_line(0, yres - 1, xres - 1, yres - 1, 0xff00aa); 122 draw_line(0, 0, 0, yres - 1, 0xff00ef); 123 draw_line(0, 0, xres - 1, yres - 1, 0xff45); 124 draw_line(xres - 1, 0, 0, yres - 1, 0xff0780); 125 126 delay(1000000); 127 128 /* 画圆 */ 129 draw_circle(xres/2, yres/2, yres/4, 0xff); 130 131 /* 输出文字 */ 132 fb_print_string(10, 10, "www.100ask.net\n\r100ask.taobao.com", 0xff); 133 }