上篇博客中进行了lcd的简单测试,这篇博客将进行更加复杂的测试——画点、画线、画圆。画线和画圆是在画点的基础上实现的,因此本篇博客重点实现画点操作。
先抛出这样的一个问题,已知:
(x,y)的坐标;
bpp;
xres;
yres;
那么,如何在framebuffer中获得像素的地址呢?
(x,y)像素的起始地址 = fb_base +(xres * bpp /8)* y +x * bpp/8
(xres * bpp /8)表示一行占据多少个字节,乘以y表示y行共占据多少个像素
2)在framebuffer.c中实现画点操作
1 #include "lcd.h"
2
3 /* 实现画点 */
4
5 /* 获得LCD参数 */
6 static unsigned int fb_base;
7 static int xres, yres, bpp;
8
9 void fb_get_lcd_params(void)
10 {
11 get_lcd_params(&fb_base, &xres, &yres, &bpp);
12 }
13
14 /* rgb: 0x00RRGGBB */
15 unsigned short convert32bppto16bpp(unsigned int rgb)
16 {
17 int r = (rgb >> 16)& 0xff; /*将红色的值拿到*/
18 int g = (rgb >> 8) & 0xff; /*将绿色的值拿到*/
19 int b = rgb & 0xff; /*将蓝色的值拿到*/
20
21 /* rgb565 */ /*需要将rgb组成一个16位的数,怎么组*/
22 r = r >> 3; /*将红色的值右移3位,相当于取高5位。为什么这么取,得看16bpp数据的组织格式*/
23 g = g >> 2; /*将绿色的值右移2位,相当于取高6位。为什么这么取,得看16bpp数据的组织格式*/
24 b = b >> 3; /*将蓝色的值右移3位,相当于取高5位。为什么这么取,得看16bpp数据的组织格式*/
25
26 return ((r<<11) | (g<<5) | (b)); /*组合成16位的数据*/
27 }
28
29
30 /* color : 32bit, 0x00RRGGBB
31 * color是32位的,用的lcd是16位的,因此需要将color转换成是16位的。
32 */
33 void fb_put_pixel(int x, int y, unsigned int color)
34 {
35 unsigned char *pc; /* 8bpp */
36 unsigned short *pw; /* 16bpp */
37 unsigned int *pdw; /* 32bpp */
38
39 unsigned int pixel_base = fb_base + (xres * bpp / 8) * y + x * bpp / 8;
40
41 switch (bpp)
42 {
43 case 8:
44 pc = (unsigned char *) pixel_base;
45 *pc = color; /*这个地方是有问题的,之所以将color直接赋给*pc,是因为程序压根不会走到这。因为所使用的lcd是16位的。*/
46 break;
47 case 16:
48 pw = (unsigned short *) pixel_base;
49 *pw = convert32bppto16bpp(color);
50 break;
51 case 32:
52 pdw = (unsigned int *) pixel_base;
53 *pdw = color;
54 break;
55 }
56 }
画线、画圆的操作在geometry.c中实现,它不是我们的重点,直接拿别人的使用即可。只需要将自己写的画点的函数fb_put_pixel用上即可
1 #include "framebuffer.h"
2
3 /*
4 * http://blog.csdn.net/p1126500468/article/details/50428613
5 */
6
7 //-------------画圆函数。参数:圆心,半径,颜色----------
8 // 画1/8圆 然后其他7/8对称画
9 // ---------------->X
10 // |(0,0) 0
11 // | 7 1
12 // | 6 2
13 // | 5 3
14 // (Y)V 4
15 //
16 // L = x^2 + y^2 - r^2
17 void draw_circle(int x, int y, int r, int color)
18 {
19 int a, b, num;
20 a = 0;
21 b = r;
22 while(22 * b * b >= r * r) // 1/8圆即可
23 {
24 fb_put_pixel(x + a, y - b,color); // 0~1
25 fb_put_pixel(x - a, y - b,color); // 0~7
26 fb_put_pixel(x - a, y + b,color); // 4~5
27 fb_put_pixel(x + a, y + b,color); // 4~3
28
29 fb_put_pixel(x + b, y + a,color); // 2~3
30 fb_put_pixel(x + b, y - a,color); // 2~1
31 fb_put_pixel(x - b, y - a,color); // 6~7
32 fb_put_pixel(x - b, y + a,color); // 6~5
33
34 a++;
35 num = (a * a + b * b) - r*r;
36 if(num > 0)
37 {
38 b--;
39 a--;
40 }
41 }
42 }
43
44 //-----------画线。参数:起始坐标,终点坐标,颜色--------
45 void draw_line(int x1,int y1,int x2,int y2,int color)
46 {
47 int dx,dy,e;
48 dx=x2-x1;
49 dy=y2-y1;
50 if(dx>=0)
51 {
52 if(dy >= 0) // dy>=0
53 {
54 if(dx>=dy) // 1/8 octant
55 {
56 e=dy-dx/2;
57 while(x1<=x2)
58 {
59 fb_put_pixel(x1,y1,color);
60 if(e>0){y1+=1;e-=dx;}
61 x1+=1;
62 e+=dy;
63 }
64 }
65 else // 2/8 octant
66 {
67 e=dx-dy/2;
68 while(y1<=y2)
69 {
70 fb_put_pixel(x1,y1,color);
71 if(e>0){x1+=1;e-=dy;}
72 y1+=1;
73 e+=dx;
74 }
75 }
76 }
77 else // dy<0
78 {
79 dy=-dy; // dy=abs(dy)
80 if(dx>=dy) // 8/8 octant
81 {
82 e=dy-dx/2;
83 while(x1<=x2)
84 {
85 fb_put_pixel(x1,y1,color);
86 if(e>0){y1-=1;e-=dx;}
87 x1+=1;
88 e+=dy;
89 }
90 }
91 else // 7/8 octant
92 {
93 e=dx-dy/2;
94 while(y1>=y2)
95 {
96 fb_put_pixel(x1,y1,color);
97 if(e>0){x1+=1;e-=dy;}
98 y1-=1;
99 e+=dx;
100 }
101 }
102 }
103 }
104 else //dx<0
105 {
106 dx=-dx; //dx=abs(dx)
107 if(dy >= 0) // dy>=0
108 {
109 if(dx>=dy) // 4/8 octant
110 {
111 e=dy-dx/2;
112 while(x1>=x2)
113 {
114 fb_put_pixel(x1,y1,color);
115 if(e>0){y1+=1;e-=dx;}
116 x1-=1;
117 e+=dy;
118 }
119 }
120 else // 3/8 octant
121 {
122 e=dx-dy/2;
123 while(y1<=y2)
124 {
125 fb_put_pixel(x1,y1,color);
126 if(e>0){x1-=1;e-=dy;}
127 y1+=1;
128 e+=dx;
129 }
130 }
131 }
132 else // dy<0
133 {
134 dy=-dy; // dy=abs(dy)
135 if(dx>=dy) // 5/8 octant
136 {
137 e=dy-dx/2;
138 while(x1>=x2)
139 {
140 fb_put_pixel(x1,y1,color);
141 if(e>0){y1-=1;e-=dx;}
142 x1-=1;
143 e+=dy;
144 }
145 }
146 else // 6/8 octant
147 {
148 e=dx-dy/2;
149 while(y1>=y2)
150 {
151 fb_put_pixel(x1,y1,color);
152 if(e>0){x1-=1;e-=dy;}
153 y1-=1;
154 e+=dx;
155 }
156 }
157 }
158 }
159 }
3)在led_test.c中,需要测什么?看下图:
1 #include "geometry.h"
2
3 void lcd_test(void)
4 {
5 unsigned int fb_base;
6 int xres, yres, bpp;
7 int x, y;
8 unsigned short *p;
9 unsigned int *p2;
10
11 /* 初始化LCD */
12 lcd_init();
13
14 /* 使能LCD */
15 lcd_enable();
16
17 /* 获得LCD的参数: fb_base, xres, yres, bpp */
18 get_lcd_params(&fb_base, &xres, &yres, &bpp);
19 fb_get_lcd_params();
20
21 /* 往framebuffer中写数据 */
22 if (bpp == 16)
23 {
24 /* 让LCD输出整屏的红色 */
25
26 /* 565: 0xf800 */
27
28 p = (unsigned short *)fb_base;
29 for (x = 0; x < xres; x++)
30 for (y = 0; y < yres; y++)
31 *p++ = 0xf800;
32
33 /* green */
34 p = (unsigned short *)fb_base;
35 for (x = 0; x < xres; x++)
36 for (y = 0; y < yres; y++)
37 *p++ = 0x7e0;
38
39 /* blue */
40 p = (unsigned short *)fb_base;
41 for (x = 0; x < xres; x++)
42 for (y = 0; y < yres; y++)
43 *p++ = 0x1f;
44
45 /* black */
46 p = (unsigned short *)fb_base;
47 for (x = 0; x < xres; x++)
48 for (y = 0; y < yres; y++)
49 *p++ = 0;
50
51 }
52
53
54 delay(1000000);
55
56 /* 画线 */
57 draw_line(0, 0, xres - 1, 0, 0xff0000);
58 draw_line(xres - 1, 0, xres - 1, yres - 1, 0xffff00);
59 draw_line(0, yres - 1, xres - 1, yres - 1, 0xff00aa);
60 draw_line(0, 0, 0, yres - 1, 0xff00ef);
61 draw_line(0, 0, xres - 1, yres - 1, 0xff4500);
62 draw_line(xres - 1, 0, 0, yres - 1, 0xff0780);
63
64 delay(1000000);
65
66 /* 画圆 */
67 draw_circle(xres/2, yres/2, yres/4, 0xff00);
68 }
所看到的现象就是,lcd显输出整屏红色----->绿色------->蓝色------->黑色---------->画线--------->画圆