最近修改了LCD驅(qū)動(dòng),方便支持可以多屏顯示以及坐標(biāo)支持負(fù)坐標(biāo),超出顯示范圍時(shí)截取顯示部分。
首先增加了一個(gè)屏幕數(shù)據(jù)結(jié)構(gòu)體
typedef struct lcd_port_t
{
int16_t x;
int16_t y;
uint16_t w;
uint16_t h;
uint8_t buff[LCD_BUFF_SIZE * 2];
void ( * draw)(int16_t x1,int16_t y1,int16_t x2,int16_t y2,const uint8_t *pbuff);
void ( * setwindow)(int16_t x,int16_t y, int16_t width, int16_t height);
}lcd_port_t;
其中x,y標(biāo)識(shí)這個(gè)lcd屏幕在畫板上相對(duì)的偏移位置坐標(biāo),可以正負(fù)數(shù)據(jù)。
w,h標(biāo)識(shí)這個(gè)lcd屏幕可以顯示的寬度和高度。這2個(gè)值可以<=屏幕實(shí)際的寬度和高度。
buff是lcd繪圖的內(nèi)部緩存。
draw函數(shù)指針代表本LCD的繪圖函數(shù)。
setwindow用于設(shè)置本LCD的允許顯示的x,y相對(duì)坐標(biāo)和w,h顯示范圍。
//LCD_CNT代表支持的屏幕個(gè)數(shù)。這里是1個(gè)。
lcd_port_t __spilcd[LCD_CNT] =
{
{
.x = 0,
.y = 0,
.w = LCD_W,
.h = LCD_H,
.draw = lcd_draw_image,
.setwindow = lcd_set_window,
},
};
下面是設(shè)置顯示范圍函數(shù)
void lcd_set_window(int16_t x,int16_t y, int16_t width, int16_t height)
{
__spilcd[0].x = x;
__spilcd[0].y = y;
__spilcd[0].w = width;
__spilcd[0].h = height;
}
最重要的繪圖函數(shù)如下,后面所有繪圖都基于這個(gè)繪圖函數(shù)。
void lcd_draw_image(int16_t x1,int16_t y1,int16_t x2,int16_t y2,const uint8_t *pbuf)
{
int16_t i,j;
int16_t x_s,y_s,x_e, y_e;
uint8_t *ptr,*p;
if (pbuf == NULL) return;
//這里坐標(biāo)減去屏幕相對(duì)坐標(biāo)就是屏幕映射的顯示坐標(biāo)位置
x1 -= __spilcd[0].x;
x2 -= __spilcd[0].x;
y1 -= __spilcd[0].y;
y2 -= __spilcd[0].y;
if(x1 >= __spilcd[0].w) return;
else if(x1 >= 0) x_s = x1;
else x_s = 0;
if(x2 >= __spilcd[0].w) x_e = __spilcd[0].w - 1;
else if(x2 >= 0) x_e = x2;
else return;
if(y1 >= __spilcd[0].h) return;
else if(y1 >= 0) y_s = y1;
else y_s = 0;
if(y2 >= __spilcd[0].h) y_e = __spilcd[0].h - 1;
else if(y2 >= 0) y_e = y2;
else return;
ptr = (uint8_t *)pbuf + (y_s - y1) * 2 * (x2 - x1 + 1);
SPILCD_SetRegin(x_s, y_s, x_e, y_e);
for (i = y_s; i <= y_e; i++)
{
ptr += (x_s - x1) * 2;
p = __spilcd[0].buff;
for (j = x_s; j <= x_e; j++)
{
*p ++ = *ptr++;
*p ++ = *ptr++;
}
ptr += (x2 - x_e) * 2;
SPILCD_WriteMultiData(__spilcd[0].buff,(p - __spilcd[0].buff));
}
}
下面就是基于LCD屏驅(qū)動(dòng)繪圖的API
uint8_t lcd_line_buff[LCD_BUFF_SIZE * 2 * 2]; //長(zhǎng)邊的2倍緩存
void Lcd_DrawImage(int16_t x1,int16_t y1,int16_t x2,int16_t y2,const uint8_t *pbuf)
{
uint32_t i;
for(i=0;i<LCD_CNT;i++)
{
__spilcd[i].draw(x1,y1,x2,y2,pbuf);
}
}
void Lcd_DrawPoint(int16_t x,int16_t y,uint16_t color)
{
lcd_line_buff[0] = color>>8;
lcd_line_buff[1] = color;
Lcd_DrawImage(x,y,x,y,lcd_line_buff);
}
void Lcd_DrawCircle(int16_t x0, int16_t y0, uint16_t r,uint16_t color)
{
int a, b;
int di;
if(r <= 0) return;
else if(r == 1)
{
Lcd_DrawPoint(x0, y0, color);
return;
}
a = 0;
b = r;
di = 3 - (r << 1);
while (a <= b)
{
Lcd_DrawPoint(x0 - b, y0 - a, color);
Lcd_DrawPoint(x0 + b, y0 - a, color);
Lcd_DrawPoint(x0 - b, y0 + a, color);
Lcd_DrawPoint(x0 + b, y0 + a, color);
Lcd_DrawPoint(x0 - a, y0 - b, color);
Lcd_DrawPoint(x0 + a, y0 - b, color);
Lcd_DrawPoint(x0 - a, y0 + b, color);
Lcd_DrawPoint(x0 + a, y0 + b, color);
Lcd_DrawPoint(x0 - b, y0 - a, color);
a++;
//Bresenham
if (di < 0)di += 4 * a + 6;
else
{
di += 10 + 4 * (a - b);
b--;
}
Lcd_DrawPoint(x0 + a, y0 + b, color);
}
}
void Lcd_DrawHLine(int16_t x1, int16_t y1, int16_t x2,uint16_t color)
{
int16_t i;
uint8_t *p;
p = lcd_line_buff;
for(i=x1;i<=x2;i++)
{
*p ++ = color>>8;
*p ++ = color;
}
Lcd_DrawImage(x1,y1,x2,y1,lcd_line_buff);
}
void Lcd_DrawVLine(int16_t x1, int16_t y1, int16_t y2,uint16_t color)
{
int16_t i;
uint8_t *p;
p = lcd_line_buff;
for(i=y1;i<=y2;i++)
{
*p ++ = color>>8;
*p ++ = color;
}
Lcd_DrawImage(x1,y1,x1,y2,lcd_line_buff);
}
void Lcd_DrawRect(int16_t x1,int16_t y1,int16_t x2,int16_t y2,uint16_t color)
{
Lcd_DrawHLine(x1, y1, x2, color);
Lcd_DrawHLine(x1, y2, x2, color);
Lcd_DrawVLine(x1, y1, y2, color);
Lcd_DrawVLine(x2, y1, y2, color);
}
void Lcd_Fill(int16_t x1,int16_t y1,int16_t x2,int16_t y2, uint16_t color)
{
int i,j;
uint8_t *p;
for(j=y1;j<=y2;j++)
{
p = lcd_line_buff;
for(i=x1;i<=x2;i++)
{
*p ++ = color>>8;
*p ++ = color;
}
Lcd_DrawImage(x1,j,x2,j,lcd_line_buff);
}
}
void Lcd_FillCircle(int16_t x0, int16_t y0, uint16_t r,uint16_t color)
{
int a, b;
int di;
if(r <= 0) return;
else if(r == 1)
{
Lcd_DrawPoint(x0, y0, color);
return;
}
a = 0;
b = r;
di = 3 - (r << 1);
while (a <= b)
{
Lcd_DrawHLine(x0 - b, y0 - a, x0 + b, color);
Lcd_DrawHLine(x0 - a, y0 + b, x0 + a, color);
Lcd_DrawHLine(x0 - a, y0 - b, x0 + a, color);
Lcd_DrawHLine(x0 - b, y0 + a, x0 + b, color);
Lcd_DrawPoint(x0 - b, y0 - a, color);
a++;
//Bresenham
if (di < 0)di += 4 * a + 6;
else
{
di += 10 + 4 * (a - b);
b--;
}
Lcd_DrawPoint(x0 + a, y0 + b, color);
}
}
void Lcd_Clear(uint16_t color)
{
uint32_t i;
for(i=0;i<LCD_CNT;i++)
{
Lcd_Fill(__spilcd[i].x,__spilcd[i].y,__spilcd[i].w-1,__spilcd[i].h-1,color);
}
}
//字符點(diǎn)陣?yán)L制
void Lcd_CharDot(int16_t x1, int16_t y1, uint16_t w, uint16_t h,const uint8_t *pbuf,uint16_t f_color,uint16_t b_color)
{
int16_t i,j;
uint8_t *p,*ptr;
if((pbuf == NULL)||(w == 0)||(h == 0)) return ;
ptr = (uint8_t *)pbuf;
for(i=0;i<h;i++)
{
p = lcd_line_buff;
for(j=0;j<w;)
{
if(*ptr & (0x80>>(j&0x07)))
{
*p ++ = f_color>>8;
*p ++ = f_color;
}else
{
*p ++ = b_color>>8;
*p ++ = b_color;
}
j++;
if(!(j&0x07))
{
ptr++;
}
}
Lcd_DrawImage(x1,y1+i,x1+w-1,y1+i,lcd_line_buff);
}
}
int32_t Disp0_DrawBitmap(int16_t x,int16_t y, int16_t width, int16_t height, const uint8_t *bitmap)
{
Lcd_DrawImage(x,y,x+width-1,y+height-1,bitmap);
return 0;
}
下面添加shell命令來測(cè)試各個(gè)API繪圖函數(shù):
#include "nr_micro_shell.h"
extern const unsigned char gImage_1[];
/* GLCD RGB color definitions */
#define GLCD_COLOR_BLACK 0x0000 /* 0, 0, 0 */
#define GLCD_COLOR_NAVY 0x000F /* 0, 0, 128 */
#define GLCD_COLOR_DARK_GREEN 0x03E0 /* 0, 128, 0 */
#define GLCD_COLOR_DARK_CYAN 0x03EF /* 0, 128, 128 */
#define GLCD_COLOR_MAROON 0x7800 /* 128, 0, 0 */
#define GLCD_COLOR_PURPLE 0x780F /* 128, 0, 128 */
#define GLCD_COLOR_OLIVE 0x7BE0 /* 128, 128, 0 */
#define GLCD_COLOR_LIGHT_GREY 0xC618 /* 192, 192, 192 */
#define GLCD_COLOR_DARK_GREY 0x7BEF /* 128, 128, 128 */
#define GLCD_COLOR_BLUE 0x001F /* 0, 0, 255 */
#define GLCD_COLOR_GREEN 0x07E0 /* 0, 255, 0 */
#define GLCD_COLOR_CYAN 0x07FF /* 0, 255, 255 */
#define GLCD_COLOR_RED 0xF800 /* 255, 0, 0 */
#define GLCD_COLOR_MAGENTA 0xF81F /* 255, 0, 255 */
#define GLCD_COLOR_YELLOW 0xFFE0 /* 255, 255, 0 */
#define GLCD_COLOR_WHITE 0xFFFF /* 255, 255, 255 */
static uint16_t g_color_f = GLCD_COLOR_WHITE,g_color_b = GLCD_COLOR_BLACK;
static int16_t g_x=0,g_y=0;
static uint16_t lcd_color_find(char *pstr)
{
if (!strcmp("black", pstr)) return GLCD_COLOR_BLACK;
else if (!strcmp("white", pstr)) return GLCD_COLOR_WHITE;
else if (!strcmp("red", pstr)) return GLCD_COLOR_RED;
else if (!strcmp("yellow", pstr)) return GLCD_COLOR_YELLOW;
else if (!strcmp("green", pstr)) return GLCD_COLOR_GREEN;
else if (!strcmp("blue", pstr)) return GLCD_COLOR_BLUE;
else if (!strcmp("purple", pstr)) return GLCD_COLOR_PURPLE;
else if (!strcmp("light", pstr)) return GLCD_COLOR_LIGHT_GREY;
else if (!strcmp("dark", pstr)) return GLCD_COLOR_DARK_GREY;
else return atoi(pstr);
}
/**
* @brief test command
*/
void shell_lcd(char argc, char *argv)
{
int color;
int x1,y1,x2,y2;
if (argc > 1)
{
if (!strcmp("clear", &argv[argv[1]]))
{
if(argc == 3)
{
color = lcd_color_find(&argv[argv[2]]);
}else if(argc == 2)
{
color = g_color_b;
}else goto lcd_end;
Lcd_Clear(color);
}else if (!strcmp("fillrect", &argv[argv[1]]))
{
if(argc == 6)
{
color = g_color_f;
}else if(argc == 7)
{
color = lcd_color_find(&argv[argv[6]]);
}else goto lcd_end;
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
x2 = atoi(&argv[argv[4]]);
y2 = atoi(&argv[argv[5]]);
if(x2 && y2) Lcd_Fill(x1,y1,x1+x2-1,y1+y2-1,color);
else printf("w h must > 0");
}else if (!strcmp("fillcircle", &argv[argv[1]]))
{
if(argc == 5)
{
color = g_color_f;
}else if(argc == 6)
{
color = lcd_color_find(&argv[argv[5]]);
}else goto lcd_end;
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
x2 = atoi(&argv[argv[4]]); //r
if(x2) Lcd_FillCircle(x1,y1,x2,color);
else printf("r must > 0");
}else if (!strcmp("vline", &argv[argv[1]]))
{
if(argc == 5)
{
color = g_color_f;
}else if(argc == 6)
{
color = lcd_color_find(&argv[argv[5]]);
}else goto lcd_end;
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
y2 = atoi(&argv[argv[4]]);
if(y2) Lcd_DrawVLine(x1,y1,y1+y2-1,color);
else printf("h must > 0");
}else if (!strcmp("hline", &argv[argv[1]]))
{
if(argc == 5)
{
color = g_color_f;
}else if(argc == 6)
{
color = lcd_color_find(&argv[argv[5]]);
}else goto lcd_end;
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
x2 = atoi(&argv[argv[4]]);
if(x2) Lcd_DrawHLine(x1,y1,x1+x2-1,color);
else printf("w must > 0");
}else if (!strcmp("circle", &argv[argv[1]]))
{
if(argc == 5)
{
color = g_color_f;
}else if(argc == 6)
{
color = lcd_color_find(&argv[argv[5]]);
}else goto lcd_end;
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
x2 = atoi(&argv[argv[4]]); //r
if(x2) Lcd_DrawCircle(x1,y1,x2,color);
else printf("r must > 0");
}else if (!strcmp("rect", &argv[argv[1]]))
{
if(argc == 6)
{
color = g_color_f;
}else if(argc == 7)
{
color = lcd_color_find(&argv[argv[6]]);
}else goto lcd_end;
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
x2 = atoi(&argv[argv[4]]);
y2 = atoi(&argv[argv[5]]);
if(x2 && y2) Lcd_DrawRect(x1,y1,x1+x2-1,y1+y2-1,color);
else printf("w h must > 0");
}else if (!strcmp("point", &argv[argv[1]]))
{
if(argc == 4)
{
color = g_color_f;
}else if(argc == 5)
{
color = lcd_color_find(&argv[argv[4]]);
}else goto lcd_end;
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
Lcd_DrawPoint(x1,y1,color);
}else if (!strcmp("color", &argv[argv[1]]))
{
if(argc == 2)
{
printf("f_color=%04X,b_color=%04Xrn",g_color_f,g_color_b);
}else if(argc == 4)
{
g_color_f = lcd_color_find(&argv[argv[2]]);
g_color_b = lcd_color_find(&argv[argv[3]]);
}else goto lcd_end;
}else if (!strcmp("move", &argv[argv[1]]))
{
if(argc == 2)
{
printf("x=%d,y=%drn",g_x,g_y);
}else if(argc == 4)
{
g_x = atoi(&argv[argv[2]]);
g_y = atoi(&argv[argv[3]]);
}else goto lcd_end;
}else if (!strcmp("display", &argv[argv[1]]))
{
if(argc == 5)
{
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
lcd_disp_str_at(x1,y1,&argv[argv[4]]);
}else goto lcd_end;
}else if (!strcmp("image", &argv[argv[1]]))
{
if(argc == 2)
{
Lcd_DrawImage(g_x,g_y,g_x+39,g_y+39,(uint8_t *)gImage_1);
}else if(argc == 4)
{
x1 = atoi(&argv[argv[2]]);
y1 = atoi(&argv[argv[3]]);
Lcd_DrawImage(x1,y1,x1+39,y1+39,(uint8_t *)gImage_1);
}else goto lcd_end;
}else goto lcd_end;
}else goto lcd_end;
return;
lcd_end:
printf("usage: lcd rn");
printf("lcd clear [color]rn");
printf("lcd fillrect x1 y1 w h [color]rn");
printf("lcd fillcircle x1 y1 r [color]rn");
printf("lcd hline x1 y1 w [color]rn");
printf("lcd vline x1 y1 h [color]rn");
printf("lcd circle x1 y1 r [color]rn");
printf("lcd rect x1 y1 w h [color]rn");
printf("lcd point x1 y1 [color]rn");
printf("lcd display x y string rn");
printf("lcd move x y rn");
printf("lcd image x y rn");
printf("lcd color f_color b_color rn");
}
NR_SHELL_CMD_EXPORT(lcd, shell_lcd, "lcd display test");
lpc845_mooncake.zip (5.9 MB, 點(diǎn)擊下方附件下載)