LCD编程_使用调色板
在前面的博客中,使用的像素格式都是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 }