1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2020-08-10 zylx first version
9 * 2022-02-01 Rudy Lo add lcd_fill_array function
10 */
11
12 #include <board.h>
13
14 #ifdef BSP_USING_SPI_LCD_ILI9488
15 #include <rtdevice.h>
16 #include "drv_spi.h"
17 #include "drv_spi_ili9488.h"
18 #include <lcd_spi_port.h>
19 #include "drv_lcd_font.h"
20 #include <rttlogo.h>
21 #include <string.h>
22
23 #if defined(PKG_USING_GUIENGINE)
24 #include <rtgui/driver.h>
25 #endif
26
27 #define DRV_DEBUG
28 #define LOG_TAG "drv.spi_lcd"
29 #include <drv_log.h>
30
31 #define LCD_DC_PIN GET_PIN(C, 7)
32
33 #define LCD_DEVICE(dev) (struct drv_lcd_device*)(dev)
34
35 #define LCD_CLEAR_SEND_NUMBER (LCD_H * LCD_W *3)
36
37 static rt_uint32_t BACK_COLOR = WHITE, FORE_COLOR = BLACK;
38 static struct rt_spi_device *spi_dev_lcd;
39
rt_hw_lcd_config(void)40 static int rt_hw_lcd_config(void)
41 {
42 spi_dev_lcd = (struct rt_spi_device *)rt_device_find("spi20");
43
44 /* config spi */
45 {
46 struct rt_spi_configuration cfg;
47 cfg.data_width = 8;
48 cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
49 cfg.max_hz = 50 * 1000 * 1000;
50
51 rt_spi_configure(spi_dev_lcd, &cfg);
52 }
53
54 return RT_EOK;
55 }
56
lcd_write_cmd(const rt_uint8_t cmd)57 static rt_err_t lcd_write_cmd(const rt_uint8_t cmd)
58 {
59 rt_size_t len;
60
61 rt_pin_write(LCD_DC_PIN, PIN_LOW);
62
63 len = rt_spi_send(spi_dev_lcd, &cmd, 1);
64
65 if (len != 1)
66 {
67 LOG_I("lcd_write_cmd error. %d", len);
68 return -RT_ERROR;
69 }
70 else
71 {
72 return RT_EOK;
73 }
74 }
75
lcd_write_data(const rt_uint8_t data)76 static rt_err_t lcd_write_data(const rt_uint8_t data)
77 {
78 rt_size_t len;
79
80 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
81
82 len = rt_spi_send(spi_dev_lcd, &data, 1);
83
84 if (len != 1)
85 {
86 LOG_I("lcd_write_data error. %d", len);
87 return -RT_ERROR;
88 }
89 else
90 {
91 return RT_EOK;
92 }
93 }
94
lcd_write_half_word(const rt_uint16_t da)95 static rt_err_t lcd_write_half_word(const rt_uint16_t da)
96 {
97 rt_size_t len;
98 char data[2] = {0};
99
100 data[0] = da >> 8;
101 data[1] = da;
102
103 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
104 len = rt_spi_send(spi_dev_lcd, data, 2);
105 if (len != 2)
106 {
107 LOG_I("lcd_write_half_word error. %d", len);
108 return -RT_ERROR;
109 }
110 else
111 {
112 return RT_EOK;
113 }
114 }
115
lcd_write_three_bytes(const rt_uint32_t da)116 static rt_err_t lcd_write_three_bytes(const rt_uint32_t da)
117 {
118 rt_size_t len;
119 char data[3] = {0};
120
121 data[0] = da >> 16;
122 data[1] = da >> 8;
123 data[2] = da;
124
125 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
126 len = rt_spi_send(spi_dev_lcd, data, 3);
127 if (len != 3)
128 {
129 LOG_I("lcd_write_half_word error. %d", len);
130 return -RT_ERROR;
131 }
132 else
133 {
134 return RT_EOK;
135 }
136 }
137
lcd_gpio_init(void)138 static void lcd_gpio_init(void)
139 {
140 rt_hw_lcd_config();
141
142 __HAL_RCC_GPIOC_CLK_ENABLE();
143 rt_pin_mode(LCD_DC_PIN, PIN_MODE_OUTPUT);
144 rt_pin_mode(LCD_BL_PIN, PIN_MODE_OUTPUT);
145 rt_pin_mode(LCD_RES_PIN, PIN_MODE_OUTPUT);
146 rt_pin_write(LCD_BL_PIN, PIN_LOW);
147 }
148
rt_hw_spi_lcd_init(void)149 int rt_hw_spi_lcd_init(void)
150 {
151 __HAL_RCC_GPIOI_CLK_ENABLE();
152 rt_hw_spi_device_attach("spi2", "spi20", GET_PIN(I, 0));
153 lcd_gpio_init();
154
155 rt_pin_write(LCD_RES_PIN, PIN_HIGH);
156 rt_thread_mdelay(10);
157 rt_pin_write(LCD_RES_PIN, PIN_LOW);
158 rt_thread_mdelay(50);
159 rt_pin_write(LCD_RES_PIN, PIN_HIGH);
160 rt_thread_mdelay(200);
161
162 //************* Start Initial Sequence **********//
163 lcd_write_cmd(0xE0);
164 lcd_write_data(0x00);
165 lcd_write_data(0x07);
166 lcd_write_data(0x0f);
167 lcd_write_data(0x0D);
168 lcd_write_data(0x1B);
169 lcd_write_data(0x0A);
170 lcd_write_data(0x3c);
171 lcd_write_data(0x78);
172 lcd_write_data(0x4A);
173 lcd_write_data(0x07);
174 lcd_write_data(0x0E);
175 lcd_write_data(0x09);
176 lcd_write_data(0x1B);
177 lcd_write_data(0x1e);
178 lcd_write_data(0x0f);
179
180 lcd_write_cmd(0xE1);
181 lcd_write_data(0x00);
182 lcd_write_data(0x22);
183 lcd_write_data(0x24);
184 lcd_write_data(0x06);
185 lcd_write_data(0x12);
186 lcd_write_data(0x07);
187 lcd_write_data(0x36);
188 lcd_write_data(0x47);
189 lcd_write_data(0x47);
190 lcd_write_data(0x06);
191 lcd_write_data(0x0a);
192 lcd_write_data(0x07);
193 lcd_write_data(0x30);
194 lcd_write_data(0x37);
195 lcd_write_data(0x0f);
196
197 lcd_write_cmd(0xC0);
198 lcd_write_data(0x10);
199 lcd_write_data(0x10);
200
201 lcd_write_cmd(0xC1);
202 lcd_write_data(0x41);
203
204 lcd_write_cmd(0xC5);
205 lcd_write_data(0x00);
206 lcd_write_data(0x22);
207 lcd_write_data(0x80);
208
209 lcd_write_cmd(0x36);
210 #ifndef LCD_HOR_SCREEN
211 lcd_write_data(0x48);
212 #else
213 lcd_write_data(0x28);
214 #endif
215
216 lcd_write_cmd(0x3A); //Interface Mode Control
217 lcd_write_data(0x66);
218
219 lcd_write_cmd(0XB0); //Interface Mode Control
220 lcd_write_data(0x00);
221 lcd_write_cmd(0xB1); //Frame rate 70HZ
222 lcd_write_data(0xB0);
223 lcd_write_data(0x11);
224 lcd_write_cmd(0xB4);
225 lcd_write_data(0x02);
226 lcd_write_cmd(0xB6); //RGB/MCU Interface Control
227 lcd_write_data(0x02);
228 lcd_write_data(0x02);
229
230 lcd_write_cmd(0xB7);
231 lcd_write_data(0xC6);
232
233 lcd_write_cmd(0xE9);
234 lcd_write_data(0x00);
235
236 lcd_write_cmd(0XF7);
237 lcd_write_data(0xA9);
238 lcd_write_data(0x51);
239 lcd_write_data(0x2C);
240 lcd_write_data(0x82);
241
242 lcd_fill(0, 0, LCD_WIDTH, LCD_HEIGHT, LCD_FULL_COLOR);
243
244 lcd_write_cmd(0x11);
245 rt_thread_mdelay(120);
246 lcd_write_cmd(0x29);
247
248 rt_thread_mdelay(50); //delay screen update to prevent screen appears white when the default color is black
249
250 return RT_EOK;
251 }
252
253 /**
254 * Set background color and foreground color
255 *
256 * @param back background color
257 * @param fore fore color
258 *
259 * @return void
260 */
lcd_set_color(rt_uint32_t back,rt_uint32_t fore)261 void lcd_set_color(rt_uint32_t back, rt_uint32_t fore)
262 {
263 BACK_COLOR = back;
264 FORE_COLOR = fore;
265 }
266
lcd_display_on(void)267 void lcd_display_on(void)
268 {
269 rt_pin_write(LCD_BL_PIN, PIN_HIGH);
270 }
271
lcd_display_off(void)272 void lcd_display_off(void)
273 {
274 rt_pin_write(LCD_BL_PIN, PIN_LOW);
275 }
276
277 /* lcd enter the minimum power consumption mode and backlight off. */
lcd_enter_sleep(void)278 void lcd_enter_sleep(void)
279 {
280 lcd_display_off();
281 rt_thread_mdelay(5);
282 lcd_write_cmd(0x28);
283 rt_thread_mdelay(10);
284 lcd_write_cmd(0x10);
285 rt_thread_mdelay(120);
286 }
287 /* lcd turn off sleep mode and backlight on. */
lcd_exit_sleep(void)288 void lcd_exit_sleep(void)
289 {
290 lcd_display_on();
291 rt_thread_mdelay(5);
292 lcd_write_cmd(0x11);
293 rt_thread_mdelay(120);
294 lcd_write_cmd(0x29);
295 }
296
297 /**
298 * Set drawing area
299 *
300 * @param x1 start of x position
301 * @param y1 start of y position
302 * @param x2 end of x position
303 * @param y2 end of y position
304 *
305 * @return void
306 */
lcd_address_set(rt_uint16_t x1,rt_uint16_t y1,rt_uint16_t x2,rt_uint16_t y2)307 void lcd_address_set(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
308 {
309 lcd_write_cmd(0x2a);
310 lcd_write_data(x1 >> 8);
311 lcd_write_data(x1);
312 lcd_write_data(x2 >> 8);
313 lcd_write_data(x2);
314
315 lcd_write_cmd(0x2b);
316 lcd_write_data(y1 >> 8);
317 lcd_write_data(y1);
318 lcd_write_data(y2 >> 8);
319 lcd_write_data(y2);
320
321 lcd_write_cmd(0x2C);
322 }
323
324 /**
325 * clear the lcd.
326 *
327 * @param color Fill color
328 *
329 * @return void
330 */
lcd_clear(rt_uint32_t color)331 void lcd_clear(rt_uint32_t color)
332 {
333 rt_uint32_t i, j;
334 rt_uint8_t data[3] = {0};
335 rt_uint8_t *buf = RT_NULL;
336
337 data[0] = color >> 16;
338 data[1] = color >> 8;
339 data[2] = color;
340 lcd_address_set(0, 0, LCD_WIDTH - 1, LCD_HEIGHT - 1);
341
342 buf = rt_malloc(LCD_BUF_SIZE);
343 if (buf)
344 {
345 /* color is 16 bit */
346 for (j = 0; j < LCD_BUF_SIZE / 3; j++)
347 {
348 buf[j * 3] = data[0];
349 buf[j * 3 + 1] = data[1];
350 buf[j * 3 + 2] = data[2];
351 }
352
353 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
354 rt_spi_send(spi_dev_lcd, buf, LCD_BUF_SIZE);
355 rt_free(buf);
356 }
357 else
358 {
359 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
360 for (i = 0; i < LCD_WIDTH; i++)
361 {
362 for (j = 0; j < LCD_HEIGHT; j++)
363 {
364 rt_spi_send(spi_dev_lcd, data, 3);
365 }
366 }
367 }
368 }
369
370 /**
371 * display a point on the lcd using the given colour.
372 *
373 * @param x x position
374 * @param y y position
375 * @param color color of point
376 *
377 * @return void
378 */
lcd_draw_point_color(rt_uint16_t x,rt_uint16_t y,rt_uint32_t color)379 void lcd_draw_point_color(rt_uint16_t x, rt_uint16_t y, rt_uint32_t color)
380 {
381 lcd_address_set(x, y, x, y);
382 lcd_write_three_bytes(color);
383 }
384
385 /**
386 * display a point on the lcd.
387 *
388 * @param x x position
389 * @param y y position
390 *
391 * @return void
392 */
lcd_draw_point(rt_uint16_t x,rt_uint16_t y)393 void lcd_draw_point(rt_uint16_t x, rt_uint16_t y)
394 {
395 lcd_draw_point_color(x, y, FORE_COLOR);
396 }
397
398 /**
399 * full color on the lcd.
400 *
401 * @param x_start start of x position
402 * @param y_start start of y position
403 * @param x_end end of x position
404 * @param y_end end of y position
405 * @param color Fill color
406 *
407 * @return void
408 */
lcd_fill(rt_uint16_t x_start,rt_uint16_t y_start,rt_uint16_t x_end,rt_uint16_t y_end,rt_uint32_t color)409 void lcd_fill(rt_uint16_t x_start, rt_uint16_t y_start, rt_uint16_t x_end, rt_uint16_t y_end, rt_uint32_t color)
410 {
411 rt_uint32_t i = 0, j = 0;
412 rt_uint32_t size = 0, size_remain = 0;
413 rt_uint8_t *fill_buf = RT_NULL;
414
415 size = (x_end - x_start) * (y_end - y_start) * 3;
416
417 if (size > LCD_CLEAR_SEND_NUMBER)
418 {
419 /* the number of remaining to be filled */
420 size_remain = size - LCD_CLEAR_SEND_NUMBER;
421 size = LCD_CLEAR_SEND_NUMBER;
422 }
423
424 lcd_address_set(x_start, y_start, x_end, y_end);
425
426 fill_buf = (rt_uint8_t *)rt_malloc(LCD_CLEAR_SEND_NUMBER);
427 if (fill_buf)
428 {
429 /* fast fill */
430 while (1)
431 {
432 for (i = 0; i < size / 3; i++)
433 {
434 fill_buf[3 * i] = color >> 16;
435 fill_buf[3 * i + 1] = color >> 8;
436 fill_buf[3 * i + 2] = color;
437 }
438 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
439 rt_spi_send(spi_dev_lcd, fill_buf, size);
440
441 /* Fill completed */
442 if (size_remain == 0)
443 break;
444
445 /* calculate the number of fill next time */
446 if (size_remain > LCD_CLEAR_SEND_NUMBER)
447 {
448 size_remain = size_remain - LCD_CLEAR_SEND_NUMBER;
449 }
450 else
451 {
452 size = size_remain;
453 size_remain = 0;
454 }
455
456 }
457 rt_free(fill_buf);
458 }
459 else
460 {
461 for (i = y_start; i <= y_end; i++)
462 {
463 for (j = x_start; j <= x_end; j++)lcd_write_three_bytes(color);
464 }
465 }
466 }
467
468 /**
469 * full color array on the lcd.
470 *
471 * @param x_start start of x position
472 * @param y_start start of y position
473 * @param x_end end of x position
474 * @param y_end end of y position
475 * @param pcolor Fill color array's pointer
476 *
477 * @return void
478 */
lcd_fill_array(rt_uint16_t x_start,rt_uint16_t y_start,rt_uint16_t x_end,rt_uint16_t y_end,void * pcolor)479 void lcd_fill_array(rt_uint16_t x_start, rt_uint16_t y_start, rt_uint16_t x_end, rt_uint16_t y_end, void *pcolor)
480 {
481 rt_uint32_t size = 0;
482 rt_uint8_t *array = RT_NULL;
483
484 size = (x_end - x_start + 1) * (y_end - y_start + 1) * 3 /* 24bit */;
485 array = (rt_uint8_t *)rt_malloc(size);
486
487 if (!array) {
488 LOG_E("not enough memory");
489 return ;
490 }
491
492 rt_uint32_t *color_p = (rt_uint32_t *)pcolor;
493
494 for (rt_uint16_t i = 0; i < size / 3; i++)
495 {
496 array[3 * i] = *color_p >> 16;
497 array[3 * i + 1] = *color_p >> 8;
498 array[3 * i + 2] = *color_p;
499 color_p++;
500 }
501
502 lcd_address_set(x_start, y_start, x_end, y_end);
503 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
504 rt_spi_send(spi_dev_lcd, array, size);
505
506 rt_free(array);
507 }
508
509 /**
510 * display a line on the lcd.
511 *
512 * @param x1 x1 position
513 * @param y1 y1 position
514 * @param x2 x2 position
515 * @param y2 y2 position
516 *
517 * @return void
518 */
lcd_draw_line(rt_uint16_t x1,rt_uint16_t y1,rt_uint16_t x2,rt_uint16_t y2)519 void lcd_draw_line(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
520 {
521 rt_uint16_t t;
522 rt_uint32_t i = 0;
523 int xerr = 0, yerr = 0, delta_x, delta_y, distance;
524 int incx, incy, row, col;
525
526 if (y1 == y2)
527 {
528 /* fast draw transverse line */
529 lcd_address_set(x1, y1, x2, y2);
530
531 rt_uint8_t line_buf[960] = {0};
532
533 for (i = 0; i < x2 - x1; i++)
534 {
535 line_buf[3 * i] = FORE_COLOR >> 16;
536 line_buf[3 * i + 1] = FORE_COLOR >> 8;
537 line_buf[3 * i + 2] = FORE_COLOR;
538 }
539
540 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
541 rt_spi_send(spi_dev_lcd, line_buf, (x2 - x1) * 3);
542
543 return ;
544 }
545
546 delta_x = x2 - x1;
547 delta_y = y2 - y1;
548 row = x1;
549 col = y1;
550 if (delta_x > 0)incx = 1;
551 else if (delta_x == 0)incx = 0;
552 else
553 {
554 incx = -1;
555 delta_x = -delta_x;
556 }
557 if (delta_y > 0)incy = 1;
558 else if (delta_y == 0)incy = 0;
559 else
560 {
561 incy = -1;
562 delta_y = -delta_y;
563 }
564 if (delta_x > delta_y)distance = delta_x;
565 else distance = delta_y;
566 for (t = 0; t <= distance + 1; t++)
567 {
568 lcd_draw_point(row, col);
569 xerr += delta_x ;
570 yerr += delta_y ;
571 if (xerr > distance)
572 {
573 xerr -= distance;
574 row += incx;
575 }
576 if (yerr > distance)
577 {
578 yerr -= distance;
579 col += incy;
580 }
581 }
582 }
583
584 /**
585 * display a rectangle on the lcd.
586 *
587 * @param x1 x1 position
588 * @param y1 y1 position
589 * @param x2 x2 position
590 * @param y2 y2 position
591 *
592 * @return void
593 */
lcd_draw_rectangle(rt_uint16_t x1,rt_uint16_t y1,rt_uint16_t x2,rt_uint16_t y2)594 void lcd_draw_rectangle(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
595 {
596 lcd_draw_line(x1, y1, x2, y1);
597 lcd_draw_line(x1, y1, x1, y2);
598 lcd_draw_line(x1, y2, x2, y2);
599 lcd_draw_line(x2, y1, x2, y2);
600 }
601
602 /**
603 * display a circle on the lcd.
604 *
605 * @param x x position of Center
606 * @param y y position of Center
607 * @param r radius
608 *
609 * @return void
610 */
lcd_draw_circle(rt_uint16_t x0,rt_uint16_t y0,rt_uint8_t r)611 void lcd_draw_circle(rt_uint16_t x0, rt_uint16_t y0, rt_uint8_t r)
612 {
613 int a, b;
614 int di;
615 a = 0;
616 b = r;
617 di = 3 - (r << 1);
618 while (a <= b)
619 {
620 lcd_draw_point(x0 - b, y0 - a);
621 lcd_draw_point(x0 + b, y0 - a);
622 lcd_draw_point(x0 - a, y0 + b);
623 lcd_draw_point(x0 - b, y0 - a);
624 lcd_draw_point(x0 - a, y0 - b);
625 lcd_draw_point(x0 + b, y0 + a);
626 lcd_draw_point(x0 + a, y0 - b);
627 lcd_draw_point(x0 + a, y0 + b);
628 lcd_draw_point(x0 - b, y0 + a);
629 a++;
630 //Bresenham
631 if (di < 0)di += 4 * a + 6;
632 else
633 {
634 di += 10 + 4 * (a - b);
635 b--;
636 }
637 lcd_draw_point(x0 + a, y0 + b);
638 }
639 }
640
lcd_show_char(rt_uint16_t x,rt_uint16_t y,rt_uint8_t data,rt_uint32_t size)641 static void lcd_show_char(rt_uint16_t x, rt_uint16_t y, rt_uint8_t data, rt_uint32_t size)
642 {
643 rt_uint8_t temp;
644 rt_uint8_t num = 0;;
645 rt_uint8_t pos, t;
646 rt_uint32_t colortemp = FORE_COLOR;
647 rt_uint8_t *font_buf = RT_NULL;
648
649 if (x > LCD_WIDTH - size / 2 || y > LCD_HEIGHT - size)return;
650
651 data = data - ' ';
652 #ifdef ASC2_1608
653 if (size == 16)
654 {
655 lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);//(x,y,x+8-1,y+16-1)
656
657 font_buf = (rt_uint8_t *)rt_malloc(size * size / 2 * 3);
658 if (!font_buf)
659 {
660 /* fast show char */
661 for (pos = 0; pos < size * (size / 2) / 8; pos++)
662 {
663 temp = asc2_1608[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
664 for (t = 0; t < 8; t++)
665 {
666 if (temp & 0x80)colortemp = FORE_COLOR;
667 else colortemp = BACK_COLOR;
668 lcd_write_three_bytes(colortemp);
669 temp <<= 1;
670 }
671 }
672 }
673 else
674 {
675 for (pos = 0; pos < size * (size / 2) / 8; pos++)
676 {
677 temp = asc2_1608[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
678 for (t = 0; t < 8; t++)
679 {
680 if (temp & 0x80)colortemp = FORE_COLOR;
681 else colortemp = BACK_COLOR;
682 font_buf[3 * (8 * pos + t)] = colortemp >> 16;
683 font_buf[3 * (8 * pos + t) + 1] = colortemp >> 8;
684 font_buf[3 * (8 * pos + t) + 2] = colortemp;
685 temp <<= 1;
686 }
687 }
688 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
689 rt_spi_send(spi_dev_lcd, font_buf, size * size / 2 * 3);
690 rt_free(font_buf);
691 }
692 }
693 else
694 #endif
695
696 #ifdef ASC2_2412
697 if (size == 24)
698 {
699 lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);
700
701 font_buf = (rt_uint8_t *)rt_malloc(size * size / 2 * 3);
702 if (!font_buf)
703 {
704 /* fast show char */
705 for (pos = 0; pos < (size * 16) / 8; pos++)
706 {
707 temp = asc2_2412[(rt_uint16_t)data * (size * 16) / 8 + pos];
708 if (pos % 2 == 0)
709 {
710 num = 8;
711 }
712 else
713 {
714 num = 4;
715 }
716
717 for (t = 0; t < num; t++)
718 {
719 if (temp & 0x80)colortemp = FORE_COLOR;
720 else colortemp = BACK_COLOR;
721 lcd_write_three_bytes(colortemp);
722 temp <<= 1;
723 }
724 }
725 }
726 else
727 {
728 for (pos = 0; pos < (size * 16) / 8; pos++)
729 {
730 temp = asc2_2412[(rt_uint16_t)data * (size * 16) / 8 + pos];
731 if (pos % 2 == 0)
732 {
733 num = 8;
734 }
735 else
736 {
737 num = 4;
738 }
739
740 for (t = 0; t < num; t++)
741 {
742 if (temp & 0x80)colortemp = FORE_COLOR;
743 else colortemp = BACK_COLOR;
744 if (num == 8)
745 {
746 font_buf[3 * (12 * (pos / 2) + t)] = colortemp >> 16;
747 font_buf[3 * (12 * (pos / 2) + t) + 1] = colortemp >> 8;
748 font_buf[3 * (12 * (pos / 2) + t) + 2] = colortemp;
749 }
750 else
751 {
752 font_buf[3 * (8 + 12 * (pos / 2) + t)] = colortemp >> 16;
753 font_buf[3 * (8 + 12 * (pos / 2) + t) + 1] = colortemp >> 8;
754 font_buf[3 * (8 + 12 * (pos / 2) + t) + 2] = colortemp;
755 }
756 temp <<= 1;
757 }
758 }
759 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
760 rt_spi_send(spi_dev_lcd, font_buf, size * size / 2 * 3);
761 rt_free(font_buf);
762 }
763 }
764 else
765 #endif
766
767 #ifdef ASC2_3216
768 if (size == 32)
769 {
770 lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);
771
772 font_buf = (rt_uint8_t *)rt_malloc(size * size / 2 * 3);
773 if (!font_buf)
774 {
775 /* fast show char */
776 for (pos = 0; pos < size * (size / 2) / 8; pos++)
777 {
778 temp = asc2_3216[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
779 for (t = 0; t < 8; t++)
780 {
781 if (temp & 0x80)colortemp = FORE_COLOR;
782 else colortemp = BACK_COLOR;
783 lcd_write_three_bytes(colortemp);
784 temp <<= 1;
785 }
786 }
787 }
788 else
789 {
790 for (pos = 0; pos < size * (size / 2) / 8; pos++)
791 {
792 temp = asc2_3216[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
793 for (t = 0; t < 8; t++)
794 {
795 if (temp & 0x80)colortemp = FORE_COLOR;
796 else colortemp = BACK_COLOR;
797 font_buf[3 * (8 * pos + t)] = colortemp >> 16;
798 font_buf[3 * (8 * pos + t) + 1] = colortemp >> 8;
799 font_buf[3 * (8 * pos + t) + 2] = colortemp;
800 temp <<= 1;
801 }
802 }
803 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
804 rt_spi_send(spi_dev_lcd, font_buf, size * size / 2 * 3);
805 rt_free(font_buf);
806 }
807 }
808 else
809 #endif
810 {
811 LOG_E("There is no any define ASC2_1208 && ASC2_2412 && ASC2_2416 && ASC2_3216 !");
812 }
813 }
814
815 /**
816 * display the number on the lcd.
817 *
818 * @param x x position
819 * @param y y position
820 * @param num number
821 * @param len length of number
822 * @param size size of font
823 *
824 * @return void
825 */
lcd_show_num(rt_uint16_t x,rt_uint16_t y,rt_uint32_t num,rt_uint8_t len,rt_uint32_t size)826 void lcd_show_num(rt_uint16_t x, rt_uint16_t y, rt_uint32_t num, rt_uint8_t len, rt_uint32_t size)
827 {
828 lcd_show_string(x, y, size, "%d", num);
829 }
830
831 /**
832 * display the string on the lcd.
833 *
834 * @param x x position
835 * @param y y position
836 * @param size size of font
837 * @param p the string to be display
838 *
839 * @return 0: display success
840 * -1: size of font is not support
841 */
lcd_show_string(rt_uint16_t x,rt_uint16_t y,rt_uint32_t size,const char * fmt,...)842 rt_err_t lcd_show_string(rt_uint16_t x, rt_uint16_t y, rt_uint32_t size, const char *fmt, ...)
843 {
844 #define LCD_STRING_BUF_LEN 128
845
846 va_list args;
847 rt_uint8_t buf[LCD_STRING_BUF_LEN] = {0};
848 rt_uint8_t *p = RT_NULL;
849
850 if (size != 16 && size != 24 && size != 32)
851 {
852 LOG_E("font size(%d) is not support!", size);
853 return -RT_ERROR;
854 }
855
856 va_start(args, fmt);
857 rt_vsnprintf((char *)buf, 100, (const char *)fmt, args);
858 va_end(args);
859
860 p = buf;
861 while (*p != '\0')
862 {
863 if (x > LCD_WIDTH - size / 2)
864 {
865 x = 0;
866 y += size;
867 }
868 if (y > LCD_HEIGHT - size)
869 {
870 y = x = 0;
871 lcd_clear(RED);
872 }
873 lcd_show_char(x, y, *p, size);
874 x += size / 2;
875 p++;
876 }
877
878 return RT_EOK;
879 }
880
881 /**
882 * display the image on the lcd.
883 *
884 * @param x x position
885 * @param y y position
886 * @param length length of image
887 * @param wide wide of image
888 * @param p image
889 *
890 * @return 0: display success
891 * -1: the image is too large
892 */
lcd_show_image(rt_uint16_t x,rt_uint16_t y,rt_uint16_t length,rt_uint16_t wide,const rt_uint8_t * p)893 rt_err_t lcd_show_image(rt_uint16_t x, rt_uint16_t y, rt_uint16_t length, rt_uint16_t wide, const rt_uint8_t *p)
894 {
895 RT_ASSERT(p);
896
897 if (x + length > LCD_WIDTH || y + wide > LCD_HEIGHT)
898 {
899 return -RT_ERROR;
900 }
901
902 lcd_address_set(x, y, x + length - 1, y + wide - 1);
903
904 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
905 rt_spi_send(spi_dev_lcd, p, length * wide * 3);
906
907 return RT_EOK;
908 }
909
910 struct drv_lcd_device
911 {
912 struct rt_device parent;
913
914 struct rt_device_graphic_info lcd_info;
915
916 struct rt_semaphore lcd_lock;
917
918 /* 0:front_buf is being used 1: back_buf is being used*/
919 rt_uint8_t cur_buf;
920 rt_uint8_t *front_buf;
921 rt_uint8_t *back_buf;
922 };
923
924 struct drv_lcd_device _lcd;
925
drv_lcd_init(struct rt_device * device)926 static rt_err_t drv_lcd_init(struct rt_device *device)
927 {
928 struct drv_lcd_device *lcd = LCD_DEVICE(device);
929 /* nothing, right now */
930 lcd = lcd;
931 return RT_EOK;
932 }
933
drv_lcd_control(struct rt_device * device,int cmd,void * args)934 static rt_err_t drv_lcd_control(struct rt_device *device, int cmd, void *args)
935 {
936 struct drv_lcd_device *lcd = LCD_DEVICE(device);
937 struct rt_device_rect_info *rect_info = RT_NULL;
938 uint32_t data_start_addr = 0;
939 uint32_t i = 0;
940
941 switch (cmd)
942 {
943 case RTGRAPHIC_CTRL_RECT_UPDATE:
944 {
945 /* update */
946 rect_info = (struct rt_device_rect_info *)args;
947 if(rect_info != NULL)
948 {
949 data_start_addr = rect_info->y * LCD_BYTES_PER_PIXEL * LCD_WIDTH + rect_info->x * LCD_BYTES_PER_PIXEL;
950 for(i = 0; i < rect_info->height; i++)
951 {
952 memcpy(&_lcd.front_buf[i * LCD_BYTES_PER_PIXEL * rect_info->width], &_lcd.lcd_info.framebuffer[data_start_addr + i * LCD_BYTES_PER_PIXEL * LCD_WIDTH], rect_info->width * LCD_BYTES_PER_PIXEL);
953 }
954 lcd_show_image(rect_info->x, rect_info->y, rect_info->width, rect_info->height, _lcd.front_buf);
955 }
956 else
957 {
958 memcpy(_lcd.front_buf, _lcd.lcd_info.framebuffer, LCD_BUF_SIZE);
959 lcd_show_image(0, 0, LCD_WIDTH, LCD_HEIGHT, _lcd.front_buf);
960 }
961 }
962 break;
963
964 case RTGRAPHIC_CTRL_GET_INFO:
965 {
966 struct rt_device_graphic_info *info = (struct rt_device_graphic_info *)args;
967
968 RT_ASSERT(info != RT_NULL);
969 info->pixel_format = lcd->lcd_info.pixel_format;
970 info->bits_per_pixel = lcd->lcd_info.bits_per_pixel;
971 info->width = lcd->lcd_info.width;
972 info->height = lcd->lcd_info.height;
973 info->framebuffer = lcd->lcd_info.framebuffer;
974 }
975 break;
976 }
977
978 return RT_EOK;
979 }
980
981 #if defined(LCD_BACKLIGHT_USING_GPIO)
turn_on_lcd_backlight(void)982 void turn_on_lcd_backlight(void)
983 {
984 rt_pin_mode(LCD_BL_PIN, PIN_MODE_OUTPUT);
985 rt_pin_write(LCD_BL_PIN, PIN_HIGH);
986 }
987 #else
turn_on_lcd_backlight(void)988 void turn_on_lcd_backlight(void)
989 {
990
991 }
992 #endif
993
994 #ifdef RT_USING_DEVICE_OPS
995 const static struct rt_device_ops lcd_ops =
996 {
997 drv_lcd_init,
998 RT_NULL,
999 RT_NULL,
1000 RT_NULL,
1001 RT_NULL,
1002 drv_lcd_control
1003 };
1004 #endif
1005
drv_lcd_ili9488_hw_init(void)1006 int drv_lcd_ili9488_hw_init(void)
1007 {
1008 rt_err_t result = RT_EOK;
1009 struct rt_device *device = &_lcd.parent;
1010
1011 /* memset _lcd to zero */
1012 memset(&_lcd, 0x00, sizeof(_lcd));
1013
1014 /* init lcd_lock semaphore */
1015 result = rt_sem_init(&_lcd.lcd_lock, "lcd_lock", 0, RT_IPC_FLAG_FIFO);
1016 if (result != RT_EOK)
1017 {
1018 LOG_E("init semaphore failed!\n");
1019 result = -RT_ENOMEM;
1020 goto __exit;
1021 }
1022
1023 /* config LCD dev info */
1024 _lcd.lcd_info.height = LCD_HEIGHT;
1025 _lcd.lcd_info.width = LCD_WIDTH;
1026 _lcd.lcd_info.bits_per_pixel = LCD_BITS_PER_PIXEL;
1027 _lcd.lcd_info.pixel_format = LCD_PIXEL_FORMAT;
1028
1029 /* malloc memory for double Buffering */
1030 _lcd.lcd_info.framebuffer = rt_malloc(LCD_BUF_SIZE);
1031 _lcd.front_buf = rt_malloc(LCD_BUF_SIZE);
1032 if (_lcd.lcd_info.framebuffer == RT_NULL || _lcd.front_buf == RT_NULL)
1033 {
1034 LOG_E("init frame buffer failed!\n");
1035 result = -RT_ENOMEM;
1036 goto __exit;
1037 }
1038
1039 /* memset buff to 0xFF */
1040 memset(_lcd.lcd_info.framebuffer, 0xFF, LCD_BUF_SIZE);
1041 memset(_lcd.front_buf, 0xFF, LCD_BUF_SIZE);
1042
1043 device->type = RT_Device_Class_Graphic;
1044 #ifdef RT_USING_DEVICE_OPS
1045 device->ops = &lcd_ops;
1046 #else
1047 device->init = drv_lcd_init;
1048 device->control = drv_lcd_control;
1049 #endif
1050
1051 /* register lcd device */
1052 rt_device_register(device, "lcd", RT_DEVICE_FLAG_RDWR);
1053
1054 /* init spi lcd */
1055 if (rt_hw_spi_lcd_init() != RT_EOK)
1056 {
1057 result = -RT_ERROR;
1058 goto __exit;
1059 }
1060 else
1061 {
1062 turn_on_lcd_backlight();
1063 }
1064
1065 #if defined(PKG_USING_GUIENGINE)
1066 rtgui_graphic_set_device(device);
1067 #endif
1068
1069 __exit:
1070 if (result != RT_EOK)
1071 {
1072 rt_sem_detach(&_lcd.lcd_lock);
1073
1074 if (_lcd.lcd_info.framebuffer)
1075 {
1076 rt_free(_lcd.lcd_info.framebuffer);
1077 }
1078
1079 if (_lcd.back_buf)
1080 {
1081 rt_free(_lcd.back_buf);
1082 }
1083
1084 if (_lcd.front_buf)
1085 {
1086 rt_free(_lcd.front_buf);
1087 }
1088 }
1089 return result;
1090 }
1091 INIT_COMPONENT_EXPORT(drv_lcd_ili9488_hw_init);
1092
1093 #ifdef DRV_DEBUG
1094 #ifdef FINSH_USING_MSH
ili9488_test()1095 int ili9488_test()
1096 {
1097 struct drv_lcd_device *lcd;
1098 lcd = (struct drv_lcd_device *)rt_device_find("lcd");
1099 struct rt_device_rect_info rect_info = {0, 0, LCD_WIDTH, LCD_HEIGHT};
1100 uint32_t i = 0;
1101
1102 lcd_clear(WHITE);
1103
1104 lcd_show_image(0, 0, 240, 69, image_rttlogo);
1105
1106 lcd_set_color(WHITE, BLACK);
1107
1108 lcd_show_string(10, 69, 16, "Hello, RT-Thread!");
1109 lcd_show_string(10, 69+16, 24, "RT-Thread");
1110 lcd_show_string(10, 69+16+24, 32, "RT-Thread");
1111
1112 lcd_draw_line(0, 69+16+24+32, LCD_H, 69+16+24+32);
1113
1114 lcd_draw_point(160, 310);
1115 for (int i = 0; i < 150; i += 4)
1116 {
1117 lcd_draw_circle(160, 310, i);
1118 }
1119
1120 rt_thread_mdelay(2000);
1121
1122 while (1)
1123 {
1124 i += 10;
1125 if(i >= 120)
1126 {
1127 i = 0;
1128 }
1129
1130 rect_info.x = i;
1131 rect_info.y = i;
1132 rect_info.width =LCD_WIDTH - 2 * i;
1133 rect_info.height =LCD_HEIGHT - 2 * i;
1134
1135 /* red */
1136 for (int i = 0; i < LCD_BUF_SIZE / 3; i++)
1137 {
1138 lcd->lcd_info.framebuffer[3 * i] = 0xFF;
1139 lcd->lcd_info.framebuffer[3 * i + 1] = 0x00;
1140 lcd->lcd_info.framebuffer[3 * i + 2] = 0x00;
1141 }
1142 lcd->parent.control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, &rect_info);
1143 rt_thread_mdelay(1000);
1144 /* green */
1145 for (int i = 0; i < LCD_BUF_SIZE / 3; i++)
1146 {
1147 lcd->lcd_info.framebuffer[3 * i] = 0x00;
1148 lcd->lcd_info.framebuffer[3 * i + 1] = 0xFF;
1149 lcd->lcd_info.framebuffer[3 * i + 2] = 0x00;
1150 }
1151 lcd->parent.control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, &rect_info);
1152 rt_thread_mdelay(1000);
1153 /* blue */
1154 for (int i = 0; i < LCD_BUF_SIZE / 3; i++)
1155 {
1156 lcd->lcd_info.framebuffer[3 * i] = 0x00;
1157 lcd->lcd_info.framebuffer[3 * i + 1] = 0x00;
1158 lcd->lcd_info.framebuffer[3 * i + 2] = 0xFF;
1159 }
1160 lcd->parent.control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, &rect_info);
1161 rt_thread_mdelay(1000);
1162 }
1163 }
1164 MSH_CMD_EXPORT(ili9488_test, test ili9488 driver);
1165 #endif /* FINSH_USING_MSH */
1166 #endif /* DRV_DEBUG */
1167 #endif /* BSP_USING_SPI_LCD_ILI9488 */
1168