上篇博客中进行了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, 0x00RRGGBB31 * 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显输出整屏红色----->绿色------->蓝色------->黑色---------->画线--------->画圆