8 #define LUAT_LOG_TAG "lcd"
11 luat_color_t BACK_COLOR
= LCD_WHITE
, FORE_COLOR
= LCD_BLACK
;
13 #define LUAT_LCD_CONF_COUNT (1)
14 static luat_lcd_conf_t
* confs
[LUAT_LCD_CONF_COUNT
] = {0};
16 void luat_lcd_execute_cmds(luat_lcd_conf_t
* conf
) {
17 uint16_t cmd
= 0,cmd_len
= 0;
20 for (size_t i
= 0; i
< conf
->opts
->init_cmds_len
; i
++){
21 cmd
= conf
->opts
->init_cmds
[i
];
22 switch(((cmd
>> 8) & 0xFF)) {
27 lcd_write_cmd_data(conf
,cmd_send
, cmds
, cmd_len
);
29 lcd_write_cmd_data(conf
,cmd_send
, NULL
, 0);
32 cmd_send
= (uint8_t)(cmd
& 0xFF);
36 luat_rtos_task_sleep(cmd
& 0xFF);
39 cmds
[cmd_len
]= (uint8_t)(cmd
& 0xFF);
45 if (i
==conf
->opts
->init_cmds_len
-1){
47 lcd_write_cmd_data(conf
,cmd_send
, cmds
, cmd_len
);
49 lcd_write_cmd_data(conf
,cmd_send
, NULL
, 0);
55 int lcd_write_data(luat_lcd_conf_t
* conf
, const uint8_t data
){
57 if (conf
->port
== LUAT_LCD_SPI_DEVICE
){
58 len
= luat_spi_device_send((luat_spi_device_t
*)(conf
->lcd_spi_device
), (const char*)&data
, 1);
60 len
= luat_spi_send(conf
->port
, (const char*)&data
, 1);
63 LLOGI("lcd_write_data error. %d", len
);
70 int lcd_write_cmd_data(luat_lcd_conf_t
* conf
,const uint8_t cmd
, const uint8_t *data
, uint8_t data_len
){
71 if (conf
->opts
->write_cmd_data
){
72 return conf
->opts
->write_cmd_data(conf
,cmd
,data
,data_len
);
75 if (conf
->interface_mode
==LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_I
|| conf
->interface_mode
==LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_II
){
76 luat_gpio_set(conf
->pin_dc
, Luat_GPIO_LOW
);
78 #ifdef LUAT_LCD_CMD_DELAY_US
79 if (conf
->dc_delay_us
){
80 luat_timer_us_delay(conf
->dc_delay_us
);
83 if (conf
->port
== LUAT_LCD_SPI_DEVICE
){
84 len
= luat_spi_device_send((luat_spi_device_t
*)(conf
->lcd_spi_device
), (const char*)&cmd
, 1);
86 len
= luat_spi_send(conf
->port
, (const char*)&cmd
, 1);
88 if (conf
->interface_mode
==LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_I
|| conf
->interface_mode
==LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_II
){
89 luat_gpio_set(conf
->pin_dc
, Luat_GPIO_HIGH
);
92 LLOGI("lcd_write_cmd error. %d", len
);
95 #ifdef LUAT_LCD_CMD_DELAY_US
96 if (conf
->dc_delay_us
){
97 luat_timer_us_delay(conf
->dc_delay_us
);
102 if (conf
->port
== LUAT_LCD_SPI_DEVICE
){
103 len
= luat_spi_device_send((luat_spi_device_t
*)(conf
->lcd_spi_device
), (const char*)data
, data_len
);
105 len
= luat_spi_send(conf
->port
, (const char*)data
, data_len
);
107 if (len
!= data_len
){
108 LLOGI("lcd_write_data error. %d", len
);
115 luat_lcd_conf_t
* luat_lcd_get_default(void) {
116 for (size_t i
= 0; i
< LUAT_LCD_CONF_COUNT
; i
++){
117 if (confs
[i
] != NULL
) {
124 const char* luat_lcd_name(luat_lcd_conf_t
* conf
) {
125 return conf
->opts
->name
;
128 int luat_lcd_init(luat_lcd_conf_t
* conf
) {
129 uint8_t direction_date
= 0;
130 conf
->is_init_done
= 0;
135 if (conf
->pin_pwr
!= LUAT_GPIO_NONE
)
136 luat_gpio_mode(conf
->pin_pwr
, Luat_GPIO_OUTPUT
, Luat_GPIO_DEFAULT
, Luat_GPIO_LOW
); // POWER
137 if (conf
->interface_mode
==LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_I
|| conf
->interface_mode
==LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_II
){
138 if (conf
->pin_dc
!= LUAT_GPIO_NONE
) luat_gpio_mode(conf
->pin_dc
, Luat_GPIO_OUTPUT
, Luat_GPIO_DEFAULT
, Luat_GPIO_HIGH
); // DC
140 luat_gpio_mode(conf
->pin_rst
, Luat_GPIO_OUTPUT
, Luat_GPIO_DEFAULT
, Luat_GPIO_LOW
); // RST
142 if (conf
->pin_pwr
!= LUAT_GPIO_NONE
)
143 luat_gpio_set(conf
->pin_pwr
, Luat_GPIO_LOW
);
144 luat_gpio_set(conf
->pin_rst
, Luat_GPIO_LOW
);
145 luat_rtos_task_sleep(100);
146 luat_gpio_set(conf
->pin_rst
, Luat_GPIO_HIGH
);
147 luat_rtos_task_sleep(120);
148 luat_lcd_wakeup(conf
);
149 luat_rtos_task_sleep(120);
152 if (conf
->opts
->init
){
153 conf
->opts
->init(conf
);
155 luat_lcd_execute_cmds(conf
);
156 if(strcmp(conf
->opts
->name
,"custom") == 0){
157 luat_heap_free(conf
->opts
->init_cmds
);
159 luat_lcd_set_direction(conf
,conf
->direction
);
162 luat_lcd_wakeup(conf
);
163 /* wait for power stability */
164 luat_rtos_task_sleep(100);
165 luat_lcd_clear(conf
,LCD_BLACK
);
167 luat_lcd_display_on(conf
);
169 conf
->is_init_done
= 1;
170 for (size_t i
= 0; i
< LUAT_LCD_CONF_COUNT
; i
++){
171 if (confs
[i
] == NULL
) {
179 int luat_lcd_close(luat_lcd_conf_t
* conf
) {
180 if (conf
->pin_pwr
!= 255)
181 luat_gpio_set(conf
->pin_pwr
, Luat_GPIO_LOW
);
185 int luat_lcd_display_off(luat_lcd_conf_t
* conf
) {
186 if (conf
->pin_pwr
!= 255)
187 luat_gpio_set(conf
->pin_pwr
, Luat_GPIO_LOW
);
188 lcd_write_cmd_data(conf
,0x28, NULL
, 0);
192 int luat_lcd_display_on(luat_lcd_conf_t
* conf
) {
193 if (conf
->pin_pwr
!= 255)
194 luat_gpio_set(conf
->pin_pwr
, Luat_GPIO_HIGH
);
195 lcd_write_cmd_data(conf
,0x29, NULL
, 0);
199 int luat_lcd_sleep(luat_lcd_conf_t
* conf
) {
200 if (conf
->pin_pwr
!= 255)
201 luat_gpio_set(conf
->pin_pwr
, Luat_GPIO_LOW
);
202 luat_rtos_task_sleep(5);
203 lcd_write_cmd_data(conf
,conf
->opts
->sleep_cmd
?conf
->opts
->sleep_cmd
:LUAT_LCD_DEFAULT_SLEEP
, NULL
, 0);
207 int luat_lcd_wakeup(luat_lcd_conf_t
* conf
) {
208 if (conf
->pin_pwr
!= 255)
209 luat_gpio_set(conf
->pin_pwr
, Luat_GPIO_HIGH
);
210 luat_rtos_task_sleep(5);
211 lcd_write_cmd_data(conf
,conf
->opts
->wakeup_cmd
?conf
->opts
->wakeup_cmd
:LUAT_LCD_DEFAULT_WAKEUP
, NULL
, 0);
215 int luat_lcd_inv_off(luat_lcd_conf_t
* conf
) {
216 lcd_write_cmd_data(conf
,0x20, NULL
, 0);
220 int luat_lcd_inv_on(luat_lcd_conf_t
* conf
) {
221 lcd_write_cmd_data(conf
,0x21, NULL
, 0);
225 int luat_lcd_set_address(luat_lcd_conf_t
* conf
,int16_t x1
, int16_t y1
, int16_t x2
, int16_t y2
) {
226 uint8_t data_x
[] = {(x1
+conf
->xoffset
)>>8,x1
+conf
->xoffset
,(x2
+conf
->xoffset
)>>8,x2
+conf
->xoffset
};
227 lcd_write_cmd_data(conf
,0x2a, data_x
, 4);
228 uint8_t data_y
[] = {(y1
+conf
->yoffset
)>>8,y1
+conf
->yoffset
,(y2
+conf
->yoffset
)>>8,y2
+conf
->yoffset
};
229 lcd_write_cmd_data(conf
,0x2b, data_y
, 4);
230 lcd_write_cmd_data(conf
,0x2c, NULL
, 0);
234 int luat_lcd_set_color(luat_color_t back
, luat_color_t fore
){
240 int luat_lcd_set_direction(luat_lcd_conf_t
* conf
, uint8_t direction
){
241 uint8_t direction_date
= 0;
242 if(direction
==0) direction_date
= conf
->opts
->direction0
;
243 else if(direction
==1) direction_date
= conf
->opts
->direction90
;
244 else if(direction
==2) direction_date
= conf
->opts
->direction180
;
245 else direction_date
= conf
->opts
->direction270
;
246 lcd_write_cmd_data(conf
,0x36, &direction_date
, 1);
250 #ifndef LUAT_USE_LCD_CUSTOM_DRAW
251 int luat_lcd_flush(luat_lcd_conf_t
* conf
) {
252 if (conf
->buff
== NULL
) {
255 //LLOGD("luat_lcd_flush range %d %d", conf->flush_y_min, conf->flush_y_max);
256 if (conf
->flush_y_max
< conf
->flush_y_min
) {
258 //LLOGD("luat_lcd_flush no need");
261 uint32_t size
= conf
->w
* (conf
->flush_y_max
- conf
->flush_y_min
+ 1) * 2;
262 luat_lcd_set_address(conf
, 0, conf
->flush_y_min
, conf
->w
- 1, conf
->flush_y_max
);
263 const char* tmp
= (const char*)(conf
->buff
+ conf
->flush_y_min
* conf
->w
);
264 if (conf
->port
== LUAT_LCD_SPI_DEVICE
){
265 luat_spi_device_send((luat_spi_device_t
*)(conf
->lcd_spi_device
), tmp
, size
);
267 luat_spi_send(conf
->port
, tmp
, size
);
271 conf
->flush_y_max
= 0;
272 conf
->flush_y_min
= conf
->h
;
277 int luat_lcd_draw(luat_lcd_conf_t
* conf
, int16_t x1
, int16_t y1
, int16_t x2
, int16_t y2
, luat_color_t
* color
) {
278 if (x1
>= conf
->w
|| y1
>= conf
->h
|| x2
< 0 || y2
< 0 || x2
< x1
|| y2
< y1
) {
279 // LLOGE("out of lcd buff range %d %d %d %d", x1, y1, x2, y2);
280 // LLOGE("out of lcd buff range %d %d %d %d %d", x1 >= conf->w, y1 >= conf->h, y2 < 0, x2 < x1, y2 < y1);
286 if (conf
->opts
->lcd_draw
)
287 return conf
->opts
->lcd_draw(conf
, x1
, y1
, x2
, y2
, color
);
289 if (conf
->buff
== NULL
) {
291 if (x1
>= 0 && y1
>= 0 && x2
<= conf
->w
&& y2
<= conf
->h
) {
292 uint32_t size
= (x2
- x1
+ 1) * (y2
- y1
+ 1);
293 // LLOGD("draw %dx%d %dx%d %d", x1, y1, x2, y2, size);
294 luat_lcd_set_address(conf
, x1
, y1
, x2
, y2
);
295 if (conf
->port
== LUAT_LCD_SPI_DEVICE
){
296 luat_spi_device_send((luat_spi_device_t
*)(conf
->lcd_spi_device
), (const char*)color
, size
* sizeof(luat_color_t
));
298 luat_spi_send(conf
->port
, (const char*)color
, size
* sizeof(luat_color_t
));
303 int line_size
= (x2
- x1
+ 1);
304 // LLOGD("want draw %dx%d %dx%d %d", x1, y1, x2, y2, line_size);
305 luat_color_t
* ptr
= (luat_color_t
*)color
;
306 for (int i
= y1
; i
<= y2
; i
++)
312 luat_color_t
* line
= ptr
;
313 int lsize
= line_size
;
322 lsize
-= (x2
- conf
->w
);
325 // LLOGD("action draw %dx%d %dx%d %d", tmp_x1, i, tmp_x2, i, lsize);
326 luat_lcd_set_address(conf
, tmp_x1
, i
, tmp_x2
, i
);
327 if (conf
->port
== LUAT_LCD_SPI_DEVICE
){
328 luat_spi_device_send((luat_spi_device_t
*)(conf
->lcd_spi_device
), (const char*)line
, lsize
* sizeof(luat_color_t
));
330 luat_spi_send(conf
->port
, (const char*)line
, lsize
* sizeof(luat_color_t
));
336 // LLOGD("超出边界,特殊处理");
341 int16_t x_end
= x2
>= conf
->w
? (conf
->w
- 1):x2
;
342 luat_color_t
* dst
= (conf
->buff
);
343 size_t lsize
= (x2
- x1
+ 1);
344 for (int16_t x
= x1
; x
<= x2
; x
++)
346 if (x
< 0 || x
>= conf
->w
)
348 for (int16_t y
= y1
; y
<= y2
; y
++)
350 if (y
< 0 || y
>= conf
->h
)
352 memcpy((char*)(dst
+ (conf
->w
* y
+ x
)), (char*)(color
+ (lsize
* (y
-y1
) + (x
-x1
))), sizeof(luat_color_t
));
356 if (y1
< conf
->flush_y_min
) {
358 conf
->flush_y_min
= y1
;
360 conf
->flush_y_min
= 0;
362 if (y2
> conf
->flush_y_max
) {
363 conf
->flush_y_max
= y2
;
369 int luat_lcd_draw_point(luat_lcd_conf_t
* conf
, int16_t x
, int16_t y
, luat_color_t color
) {
370 luat_color_t tmp
= color
;
371 if (conf
->port
!= LUAT_LCD_HW_ID_0
)
372 tmp
= color_swap(color
);// 注意, 这里需要把颜色swap了
373 return luat_lcd_draw(conf
, x
, y
, x
, y
, &tmp
);
376 int luat_lcd_clear(luat_lcd_conf_t
* conf
, luat_color_t color
){
377 luat_lcd_draw_fill(conf
, 0, 0, conf
->w
- 1, conf
->h
, color
);
381 int luat_lcd_draw_fill(luat_lcd_conf_t
* conf
,int16_t x1
,int16_t y1
,int16_t x2
,int16_t y2
, luat_color_t color
) {
385 luat_lcd_draw_line(conf
, x1
, i
, x2
, i
, color
);
390 int luat_lcd_draw_vline(luat_lcd_conf_t
* conf
, int16_t x
, int16_t y
,int16_t h
, luat_color_t color
) {
392 return luat_lcd_draw_line(conf
, x
, y
, x
, y
+ h
- 1, color
);
395 int luat_lcd_draw_hline(luat_lcd_conf_t
* conf
, int16_t x
, int16_t y
,int16_t w
, luat_color_t color
) {
397 return luat_lcd_draw_line(conf
, x
, y
, x
+ w
- 1, y
, color
);
400 int luat_lcd_draw_line(luat_lcd_conf_t
* conf
,int16_t x1
, int16_t y1
, int16_t x2
, int16_t y2
,luat_color_t color
) {
401 luat_color_t tmp
= color
;
404 int xerr
= 0, yerr
= 0, delta_x
, delta_y
, distance
;
405 int incx
, incy
, row
, col
;
406 if (x1
== x2
|| y1
== y2
) // 直线
408 size_t dots
= (x2
- x1
+ 1) * (y2
- y1
+ 1);//点数量
409 luat_color_t
* line_buf
= (luat_color_t
*) luat_heap_malloc(dots
* sizeof(luat_color_t
));
410 if (conf
->port
!= LUAT_LCD_HW_ID_0
)
411 tmp
= color_swap(color
);// 颜色swap
413 for (i
= 0; i
< dots
; i
++)
417 luat_lcd_draw(conf
, x1
, y1
, x2
, y2
, line_buf
);
418 luat_heap_free(line_buf
);
427 if (delta_x
> 0)incx
= 1;
428 else if (delta_x
== 0)incx
= 0;
434 if (delta_y
> 0)incy
= 1;
435 else if (delta_y
== 0)incy
= 0;
441 if (delta_x
> delta_y
)distance
= delta_x
;
442 else distance
= delta_y
;
443 for (t
= 0; t
<= distance
+ 1; t
++)
445 luat_lcd_draw_point(conf
,row
, col
,color
);
462 int luat_lcd_draw_rectangle(luat_lcd_conf_t
* conf
,int16_t x1
, int16_t y1
, int16_t x2
, int16_t y2
, luat_color_t color
){
463 luat_lcd_draw_line(conf
,x1
, y1
, x2
, y1
, color
);
464 luat_lcd_draw_line(conf
,x1
, y1
, x1
, y2
, color
);
465 luat_lcd_draw_line(conf
,x1
, y2
, x2
, y2
, color
);
466 luat_lcd_draw_line(conf
,x2
, y1
, x2
, y2
, color
);
470 int luat_lcd_draw_circle(luat_lcd_conf_t
* conf
,int16_t x0
, int16_t y0
, uint8_t r
, luat_color_t color
){
478 luat_lcd_draw_point(conf
,x0
- b
, y0
- a
,color
);
479 luat_lcd_draw_point(conf
,x0
+ b
, y0
- a
,color
);
480 luat_lcd_draw_point(conf
,x0
- a
, y0
+ b
,color
);
481 luat_lcd_draw_point(conf
,x0
- b
, y0
- a
,color
);
482 luat_lcd_draw_point(conf
,x0
- a
, y0
- b
,color
);
483 luat_lcd_draw_point(conf
,x0
+ b
, y0
+ a
,color
);
484 luat_lcd_draw_point(conf
,x0
+ a
, y0
- b
,color
);
485 luat_lcd_draw_point(conf
,x0
+ a
, y0
+ b
,color
);
486 luat_lcd_draw_point(conf
,x0
- b
, y0
+ a
,color
);
489 if (di
< 0)di
+= 4 * a
+ 6;
492 di
+= 10 + 4 * (a
- b
);
495 luat_lcd_draw_point(conf
,x0
+ a
, y0
+ b
,color
);