#include #include #include #include #include "lcd.h" #include "log.h" #define BIT(x) (1<>8))) #define LCD_PORT "spi2" typedef struct { int x; int y; int w; int h; }lcd_rect_t; static lcd_handle_t lcdHandle={0}; extern int st77xx_init(lcd_handle_t *h); extern int st77xx_deinit(lcd_handle_t *h); extern void st77xx_set_win(lcd_handle_t *hd, uint16_t x, uint16_t y, uint16_t w, uint16_t h); extern void st77xx_refresh(lcd_handle_t *hd, uint16_t x, uint16_t y, uint16_t w, uint16_t h, void *data, uint32_t len); extern void st77xx_rotate(lcd_handle_t *h, int rotate); extern void st77xx_draw_pixel(lcd_handle_t *hd, uint16_t x, uint16_t y, uint32_t color); extern void st77xx_fill(lcd_handle_t *h, uint32_t color); extern void st77xx_fill_rect(lcd_handle_t *hd, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint32_t color); static inline int set_point(lcd_handle_t *h, int x, int y, uint32_t data) { #if 0 int pos,bit; if(h->rotate==180) { x = h->width-1-x; y = h->height-1-y; } pos = y / 8; /* get y page */ bit = y % 8; /* get y point */ if (data) { /* if 1 */ h->buf[pos*h->width+x] |= BIT(bit); /* set 1 */ } else { h->buf[pos*h->width+x] &= ~BIT(bit); /* set 0 */ } #else st77xx_draw_pixel(h,x,y,data); #endif return 0; } static int get_color_bits(int color) { if(color==COLOR_WB) { return 1; } else if(color==COLOR_RGB8) { return 8; } else if(color==COLOR_RGB565) { return 16; } else { return 32; } } //////////////////////////////////////////////////////////// void lcd_init(int width, int height, int rotate) { lcd_handle_t *h=&lcdHandle; h->width = width; h->height = height; h->rotate = rotate; st77xx_init(h); } void lcd_deinit(void) { lcd_handle_t *h=&lcdHandle; //lcd_hw_deinit(h); } void lcd_rotate(int rotate) { lcd_handle_t *h=&lcdHandle; h->rotate = rotate; st77xx_rotate(h, rotate); } int lcd_get_rotate(void) { lcd_handle_t *h=&lcdHandle; return h->rotate; } void lcd_set_backlight(int on) { lcd_handle_t *h=&lcdHandle; } void lcd_set_win(int x, int y, int w, int h) { } void lcd_fill(uint32_t color) { lcd_handle_t *h=&lcdHandle; st77xx_fill(h, color); } void lcd_draw_line(int x1, int y1, int x2, int y2, uint32_t color) { int incx = 0, incy = 0; int delta_x = 0, delta_y = 0; int distance = 0; int t = 0; int x = 0, y = 0; int x_temp = 0, y_temp = 0; lcd_handle_t *h=&lcdHandle; /* 画斜线(Bresenham算法) */ delta_x = x2 - x1; delta_y = y2 - y1; if(delta_x > 0) { //斜线(从左到右) incx = 1; } else if(delta_x == 0) { //垂直斜线(竖线) incx = 0; } else { //斜线(从右到左) incx = -1; delta_x = -delta_x; } if(delta_y > 0) { //斜线(从左到右) incy = 1; } else if(delta_y == 0) { //水平斜线(水平线) incy = 0; } else { //斜线(从右到左) incy = -1; delta_y = -delta_y; } /* 计算画笔打点距离(取两个间距中的最大值) */ if(delta_x > delta_y) { distance = delta_x; } else { distance = delta_y; } /* 开始打点 */ x = x1; y = y1; //第一个点无效,所以t的次数加一 for(t = 0; t <= distance + 1;t++) { set_point(h, x, y, color); /* 判断离实际值最近的像素点 */ x_temp += delta_x; if(x_temp > distance) { //x方向越界,减去距离值,为下一次检测做准备 x_temp -= distance; //在x方向递增打点 x += incx; } y_temp += delta_y; if(y_temp > distance) { //y方向越界,减去距离值,为下一次检测做准备 y_temp -= distance; //在y方向递增打点 y += incy; } } } void lcd_draw_rect(int x, int y, int w, int h, uint32_t color) { int x2,y2; x2 = x + w; y2 = y + h; lcd_draw_line(x,y,x2,y,color); lcd_draw_line(x,y,x,y2,color); lcd_draw_line(x,y2,x2,y2,color); lcd_draw_line(x,y,x2,y2,color); } void lcd_fill_rect(int x, int y, int w, int h, uint32_t color) { lcd_handle_t *hd=&lcdHandle; if(w==0 || h==0) { return; } st77xx_fill_rect(hd, x, y, w, h, color); } void lcd_refresh(void) { lcd_handle_t *h=&lcdHandle; } static void set_color(lcd_handle_t *h, uint32_t color, int cnt) { int i,xcnt=(cnt>h->buflen/2)?h->buflen/2:cnt; for(i=0; ibuf[i] = color; } } int lcd_draw_char(lcd_handle_t *hd, int x, int y, int w, int h, uint8_t *c, int font, uint32_t color, uint32_t bgcolor, int vert) { uint8_t tmp; font_data_t fdata; int i,j,x0=x,y0=y; int x1=x0,y1=y0; fdata = font_data(font, c); if(h>fdata.height) { if(vert==VERTICAL_CENTER) { y1 += (h-fdata.height)/2; } else if (vert==VERTICAL_BOTTOM) { y1 += h-fdata.height; } y = y1; } int x2=x0+fdata.width,y2=y0+h; #if 1 set_color(hd, bgcolor, h*fdata.width); for(i=0; iwidth) && (yheight)) { int dx=x-x0,dy=y-y0; if(tmp&0x01) { hd->buf[dy*fdata.width+dx] = color; } } tmp >>= 1; y++; if((y-y1)>=fdata.height) { y=y1; x++; break; } } } st77xx_refresh(hd, x0, y0, fdata.width, h, hd->buf, fdata.width*h*2); #else for(i=0; iwidth) && (yheight)) { if(tmp&0x01) { set_point(hd, x, y, color); } else { set_point(hd, x, y, bgcolor); } } tmp >>= 1; y++; if((y-y1)>=fdata.height) { y=y1; x++; break; } } } #endif return fdata.width; } void lcd_draw_string(int x, int y, int w, int h, char *str, int font, uint32_t color, uint32_t bgcolor, int hori, int vert) { int r,sw,xmax=x+w; lcd_rect_t rect; uint8_t *pstr=(uint8_t*)str; lcd_handle_t *hd=&lcdHandle; sw = font_width_str(font, pstr); if(sw>w) { sw = w; } if(hori==HORIZONTAL_LEFT) { rect.x = x; } else if(hori==HORIZONTAL_RIGHT) { rect.x = x+w-sw; } else if(hori==HORIZONTAL_CENTER) { rect.x = x+(w-sw)/2; } else { return; } if(rect.x+sw>=w) { rect.w = w-rect.x; } else { rect.w = sw; } rect.y = y; rect.h = h; lcd_fill_rect(x, y, rect.x-x, h, bgcolor); while(*pstr) { r = lcd_draw_char(hd, rect.x, rect.y, rect.w, rect.h, pstr, font, color, bgcolor, vert); if(!pstr || x>=xmax) { break; } rect.x += r; pstr = font_next(pstr); } lcd_fill_rect(rect.x, y, x+w-rect.x, h, bgcolor); }