1 /*
2  * Copyright (c) 2006-2021, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author            Notes
8  * 2021-01-05     RiceChen          the first version
9  */
10 
11 #include <rtdevice.h>
12 #include "drv_spi.h"
13 #include "drv_lcd.h"
14 #include "drv_lcd_font.h"
15 #include "drv_gpio.h"
16 
17 #define DBG_SECTION_NAME    "LCD"
18 #define DBG_COLOR
19 #define DBG_LEVEL           DBG_LOG
20 #include <rtdbg.h>
21 
22 #define LCD_PWR_PIN           GET_PIN(B, 15)
23 #define LCD_DC_PIN            GET_PIN(C, 6)
24 #define LCD_RES_PIN           GET_PIN(C, 7)
25 #define LCD_CLEAR_SEND_NUMBER 5760
26 
27 rt_uint16_t BACK_COLOR = WHITE, FORE_COLOR = BLACK;
28 
29 static struct rt_spi_device *spi_dev_lcd;
30 
rt_hw_lcd_config(void)31 static int rt_hw_lcd_config(void)
32 {
33     spi_dev_lcd = (struct rt_spi_device *)rt_device_find("lcd");
34 
35     /* config spi */
36     {
37         struct rt_spi_configuration cfg;
38         cfg.data_width = 8;
39         cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_3 | RT_SPI_MSB;
40         cfg.max_hz = 42 * 1000 * 1000; /* 42M, SPI max 42MHz, lcd 4-wire spi */
41 
42         rt_spi_configure(spi_dev_lcd, &cfg);
43     }
44 
45     return RT_EOK;
46 }
47 
lcd_write_cmd(const rt_uint8_t cmd)48 static rt_err_t lcd_write_cmd(const rt_uint8_t cmd)
49 {
50     rt_size_t len;
51 
52     rt_pin_write(LCD_DC_PIN, PIN_LOW);
53 
54     len = rt_spi_send(spi_dev_lcd, &cmd, 1);
55 
56     if (len != 1)
57     {
58         LOG_I("lcd_write_cmd error. %d", len);
59         return -RT_ERROR;
60     }
61     else
62     {
63         return RT_EOK;
64     }
65 }
66 
lcd_write_data(const rt_uint8_t data)67 static rt_err_t lcd_write_data(const rt_uint8_t data)
68 {
69     rt_size_t len;
70 
71     rt_pin_write(LCD_DC_PIN, PIN_HIGH);
72 
73     len = rt_spi_send(spi_dev_lcd, &data, 1);
74 
75     if (len != 1)
76     {
77         LOG_I("lcd_write_data error. %d", len);
78         return -RT_ERROR;
79     }
80     else
81     {
82         return RT_EOK;
83     }
84 }
85 
lcd_write_half_word(const rt_uint16_t da)86 static rt_err_t lcd_write_half_word(const rt_uint16_t da)
87 {
88     rt_size_t len;
89     char data[2] = {0};
90 
91     data[0] = da >> 8;
92     data[1] = da;
93 
94     rt_pin_write(LCD_DC_PIN, PIN_HIGH);
95     len = rt_spi_send(spi_dev_lcd, data, 2);
96     if (len != 2)
97     {
98         LOG_I("lcd_write_half_word error. %d", len);
99         return -RT_ERROR;
100     }
101     else
102     {
103         return RT_EOK;
104     }
105 }
106 
lcd_gpio_init(void)107 static void lcd_gpio_init(void)
108 {
109     rt_hw_lcd_config();
110 
111     rt_pin_mode(LCD_DC_PIN, PIN_MODE_OUTPUT);
112     rt_pin_mode(LCD_RES_PIN, PIN_MODE_OUTPUT);
113 
114     rt_pin_mode(LCD_PWR_PIN, PIN_MODE_OUTPUT);
115     rt_pin_write(LCD_PWR_PIN, PIN_LOW);
116 
117     rt_pin_write(LCD_RES_PIN, PIN_LOW);
118     //wait at least 100ms for reset
119     rt_thread_delay(RT_TICK_PER_SECOND / 10);
120     rt_pin_write(LCD_RES_PIN, PIN_HIGH);
121 }
122 
rt_hw_lcd_init(void)123 static int rt_hw_lcd_init(void)
124 {
125     rt_hw_spi_device_attach("spi2", "lcd", GET_PIN(C, 3));
126     lcd_gpio_init();
127     /* Memory Data Access Control */
128     lcd_write_cmd(0x36);
129     lcd_write_data(0x00);
130     /* RGB 5-6-5-bit  */
131     lcd_write_cmd(0x3A);
132     lcd_write_data(0x65);
133     /* Porch Setting */
134     lcd_write_cmd(0xB2);
135     lcd_write_data(0x0C);
136     lcd_write_data(0x0C);
137     lcd_write_data(0x00);
138     lcd_write_data(0x33);
139     lcd_write_data(0x33);
140     /*  Gate Control */
141     lcd_write_cmd(0xB7);
142     lcd_write_data(0x72);
143     /* VCOM Setting */
144     lcd_write_cmd(0xBB);
145     lcd_write_data(0x3D);
146     /* LCM Control */
147     lcd_write_cmd(0xC0);
148     lcd_write_data(0x2C);
149     /* VDV and VRH Command Enable */
150     lcd_write_cmd(0xC2);
151     lcd_write_data(0x01);
152     /* VRH Set */
153     lcd_write_cmd(0xC3);
154     lcd_write_data(0x19);
155     /* VDV Set */
156     lcd_write_cmd(0xC4);
157     lcd_write_data(0x20);
158     /* Frame Rate Control in Normal Mode */
159     lcd_write_cmd(0xC6);
160     lcd_write_data(0x0F);
161     /* Power Control 1 */
162     lcd_write_cmd(0xD0);
163     lcd_write_data(0xA4);
164     lcd_write_data(0xA1);
165     /* Positive Voltage Gamma Control */
166     lcd_write_cmd(0xE0);
167     lcd_write_data(0xD0);
168     lcd_write_data(0x04);
169     lcd_write_data(0x0D);
170     lcd_write_data(0x11);
171     lcd_write_data(0x13);
172     lcd_write_data(0x2B);
173     lcd_write_data(0x3F);
174     lcd_write_data(0x54);
175     lcd_write_data(0x4C);
176     lcd_write_data(0x18);
177     lcd_write_data(0x0D);
178     lcd_write_data(0x0B);
179     lcd_write_data(0x1F);
180     lcd_write_data(0x23);
181     /* Negative Voltage Gamma Control */
182     lcd_write_cmd(0xE1);
183     lcd_write_data(0xD0);
184     lcd_write_data(0x04);
185     lcd_write_data(0x0C);
186     lcd_write_data(0x11);
187     lcd_write_data(0x13);
188     lcd_write_data(0x2C);
189     lcd_write_data(0x3F);
190     lcd_write_data(0x44);
191     lcd_write_data(0x51);
192     lcd_write_data(0x2F);
193     lcd_write_data(0x1F);
194     lcd_write_data(0x1F);
195     lcd_write_data(0x20);
196     lcd_write_data(0x23);
197     /* Display Inversion On */
198     lcd_write_cmd(0x21);
199     /* Sleep Out */
200     lcd_write_cmd(0x11);
201     /* wait for power stability */
202     rt_thread_mdelay(100);
203 
204     lcd_clear(WHITE);
205         lcd_show_string(0, 0, 32, "RT-Thread");
206 
207     /* display on */
208     rt_pin_write(LCD_PWR_PIN, PIN_HIGH);
209     lcd_write_cmd(0x29);
210 
211     return RT_EOK;
212 }
213 INIT_DEVICE_EXPORT(rt_hw_lcd_init);
214 
215 /**
216  * Set background color and foreground color
217  *
218  * @param   back    background color
219  * @param   fore    fore color
220  *
221  * @return  void
222  */
lcd_set_color(rt_uint16_t back,rt_uint16_t fore)223 void lcd_set_color(rt_uint16_t back, rt_uint16_t fore)
224 {
225     BACK_COLOR = back;
226     FORE_COLOR = fore;
227 }
228 
lcd_display_on(void)229 void lcd_display_on(void)
230 {
231     rt_pin_write(LCD_PWR_PIN, PIN_HIGH);
232 }
233 
lcd_display_off(void)234 void lcd_display_off(void)
235 {
236     rt_pin_write(LCD_PWR_PIN, PIN_LOW);
237 }
238 
239 /* lcd enter the minimum power consumption mode and backlight off. */
lcd_enter_sleep(void)240 void lcd_enter_sleep(void)
241 {
242     rt_pin_write(LCD_PWR_PIN, PIN_LOW);
243     rt_thread_mdelay(5);
244     lcd_write_cmd(0x10);
245 }
246 /* lcd turn off sleep mode and backlight on. */
lcd_exit_sleep(void)247 void lcd_exit_sleep(void)
248 {
249     rt_pin_write(LCD_PWR_PIN, PIN_HIGH);
250     rt_thread_mdelay(5);
251     lcd_write_cmd(0x11);
252     rt_thread_mdelay(120);
253 }
254 
255 /**
256  * Set drawing area
257  *
258  * @param   x1      start of x position
259  * @param   y1      start of y position
260  * @param   x2      end of x position
261  * @param   y2      end of y position
262  *
263  * @return  void
264  */
lcd_address_set(rt_uint16_t x1,rt_uint16_t y1,rt_uint16_t x2,rt_uint16_t y2)265 void lcd_address_set(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
266 {
267     lcd_write_cmd(0x2a);
268     lcd_write_data(x1 >> 8);
269     lcd_write_data(x1);
270     lcd_write_data(x2 >> 8);
271     lcd_write_data(x2);
272 
273     lcd_write_cmd(0x2b);
274     lcd_write_data(y1 >> 8);
275     lcd_write_data(y1);
276     lcd_write_data(y2 >> 8);
277     lcd_write_data(y2);
278 
279     lcd_write_cmd(0x2C);
280 }
281 
282 /**
283  * clear the lcd.
284  *
285  * @param   color       Fill color
286  *
287  * @return  void
288  */
lcd_clear(rt_uint16_t color)289 void lcd_clear(rt_uint16_t color)
290 {
291     rt_uint16_t i, j;
292     rt_uint8_t data[2] = {0};
293     rt_uint8_t *buf = RT_NULL;
294 
295     data[0] = color >> 8;
296     data[1] = color;
297     lcd_address_set(0, 0, LCD_W - 1, LCD_H - 1);
298 
299     /* 5760 = 240*240/20 */
300     buf = rt_malloc(LCD_CLEAR_SEND_NUMBER);
301     if (buf)
302     {
303         /* 2880 = 5760/2 color is 16 bit */
304         for (j = 0; j < LCD_CLEAR_SEND_NUMBER / 2; j++)
305         {
306             buf[j * 2] =  data[0];
307             buf[j * 2 + 1] =  data[1];
308         }
309 
310         rt_pin_write(LCD_DC_PIN, PIN_HIGH);
311         for (i = 0; i < 20; i++)
312         {
313             rt_spi_send(spi_dev_lcd, buf, LCD_CLEAR_SEND_NUMBER);
314         }
315         rt_free(buf);
316     }
317     else
318     {
319         rt_pin_write(LCD_DC_PIN, PIN_HIGH);
320         for (i = 0; i < LCD_W; i++)
321         {
322             for (j = 0; j < LCD_H; j++)
323             {
324                 rt_spi_send(spi_dev_lcd, data, 2);
325             }
326         }
327     }
328 }
329 
330 /**
331  * display a point on the lcd.
332  *
333  * @param   x   x position
334  * @param   y   y position
335  *
336  * @return  void
337  */
lcd_draw_point(rt_uint16_t x,rt_uint16_t y)338 void lcd_draw_point(rt_uint16_t x, rt_uint16_t y)
339 {
340     lcd_address_set(x, y, x, y);
341     lcd_write_half_word(FORE_COLOR);
342 }
343 
344 /**
345  * display a point on the lcd using the given colour.
346  *
347  * @param   x       x position
348  * @param   y       y position
349  * @param   color   color of point
350  *
351  * @return  void
352  */
lcd_draw_point_color(rt_uint16_t x,rt_uint16_t y,rt_uint16_t color)353 void lcd_draw_point_color(rt_uint16_t x, rt_uint16_t y, rt_uint16_t color)
354 {
355     lcd_address_set(x, y, x, y);
356     lcd_write_half_word(color);
357 }
358 
359 /**
360  * full color on the lcd.
361  *
362  * @param   x_start     start of x position
363  * @param   y_start     start of y position
364  * @param   x_end       end of x position
365  * @param   y_end       end of y position
366  * @param   color       Fill color
367  *
368  * @return  void
369  */
lcd_fill(rt_uint16_t x_start,rt_uint16_t y_start,rt_uint16_t x_end,rt_uint16_t y_end,rt_uint16_t color)370 void lcd_fill(rt_uint16_t x_start, rt_uint16_t y_start, rt_uint16_t x_end, rt_uint16_t y_end, rt_uint16_t color)
371 {
372     rt_uint16_t i = 0, j = 0;
373     rt_uint32_t size = 0, size_remain = 0;
374     rt_uint8_t *fill_buf = RT_NULL;
375 
376     size = (x_end - x_start) * (y_end - y_start) * 2;
377 
378     if (size > LCD_CLEAR_SEND_NUMBER)
379     {
380         /* the number of remaining to be filled */
381         size_remain = size - LCD_CLEAR_SEND_NUMBER;
382         size = LCD_CLEAR_SEND_NUMBER;
383     }
384 
385     lcd_address_set(x_start, y_start, x_end, y_end);
386 
387     fill_buf = (rt_uint8_t *)rt_malloc(size);
388     if (fill_buf)
389     {
390         /* fast fill */
391         while (1)
392         {
393             for (i = 0; i < size / 2; i++)
394             {
395                 fill_buf[2 * i] = color >> 8;
396                 fill_buf[2 * i + 1] = color;
397             }
398             rt_pin_write(LCD_DC_PIN, PIN_HIGH);
399             rt_spi_send(spi_dev_lcd, fill_buf, size);
400 
401             /* Fill completed */
402             if (size_remain == 0)
403                 break;
404 
405             /* calculate the number of fill next time */
406             if (size_remain > LCD_CLEAR_SEND_NUMBER)
407             {
408                 size_remain = size_remain - LCD_CLEAR_SEND_NUMBER;
409             }
410             else
411             {
412                 size = size_remain;
413                 size_remain = 0;
414             }
415         }
416         rt_free(fill_buf);
417     }
418     else
419     {
420         for (i = y_start; i <= y_end; i++)
421         {
422             for (j = x_start; j <= x_end; j++)lcd_write_half_word(color);
423         }
424     }
425 }
426 
427 /**
428  * display a line on the lcd.
429  *
430  * @param   x1      x1 position
431  * @param   y1      y1 position
432  * @param   x2      x2 position
433  * @param   y2      y2 position
434  *
435  * @return  void
436  */
lcd_draw_line(rt_uint16_t x1,rt_uint16_t y1,rt_uint16_t x2,rt_uint16_t y2)437 void lcd_draw_line(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
438 {
439     rt_uint16_t t;
440     rt_uint32_t i = 0;
441     int xerr = 0, yerr = 0, delta_x, delta_y, distance;
442     int incx, incy, row, col;
443 
444     if (y1 == y2)
445     {
446         /* fast draw transverse line */
447         lcd_address_set(x1, y1, x2, y2);
448 
449         rt_uint8_t line_buf[480] = {0};
450 
451         for (i = 0; i < x2 - x1; i++)
452         {
453             line_buf[2 * i] = FORE_COLOR >> 8;
454             line_buf[2 * i + 1] = FORE_COLOR;
455         }
456 
457         rt_pin_write(LCD_DC_PIN, PIN_HIGH);
458         rt_spi_send(spi_dev_lcd, line_buf, (x2 - x1) * 2);
459 
460         return ;
461     }
462 
463     delta_x = x2 - x1;
464     delta_y = y2 - y1;
465     row = x1;
466     col = y1;
467     if (delta_x > 0)incx = 1;
468     else if (delta_x == 0)incx = 0;
469     else
470     {
471         incx = -1;
472         delta_x = -delta_x;
473     }
474     if (delta_y > 0)incy = 1;
475     else if (delta_y == 0)incy = 0;
476     else
477     {
478         incy = -1;
479         delta_y = -delta_y;
480     }
481     if (delta_x > delta_y)distance = delta_x;
482     else distance = delta_y;
483     for (t = 0; t <= distance + 1; t++)
484     {
485         lcd_draw_point(row, col);
486         xerr += delta_x ;
487         yerr += delta_y ;
488         if (xerr > distance)
489         {
490             xerr -= distance;
491             row += incx;
492         }
493         if (yerr > distance)
494         {
495             yerr -= distance;
496             col += incy;
497         }
498     }
499 }
500 
501 /**
502  * display a rectangle on the lcd.
503  *
504  * @param   x1      x1 position
505  * @param   y1      y1 position
506  * @param   x2      x2 position
507  * @param   y2      y2 position
508  *
509  * @return  void
510  */
lcd_draw_rectangle(rt_uint16_t x1,rt_uint16_t y1,rt_uint16_t x2,rt_uint16_t y2)511 void lcd_draw_rectangle(rt_uint16_t x1, rt_uint16_t y1, rt_uint16_t x2, rt_uint16_t y2)
512 {
513     lcd_draw_line(x1, y1, x2, y1);
514     lcd_draw_line(x1, y1, x1, y2);
515     lcd_draw_line(x1, y2, x2, y2);
516     lcd_draw_line(x2, y1, x2, y2);
517 }
518 
519 /**
520  * display a circle on the lcd.
521  *
522  * @param   x       x position of Center
523  * @param   y       y position of Center
524  * @param   r       radius
525  *
526  * @return  void
527  */
lcd_draw_circle(rt_uint16_t x0,rt_uint16_t y0,rt_uint8_t r)528 void lcd_draw_circle(rt_uint16_t x0, rt_uint16_t y0, rt_uint8_t r)
529 {
530     int a, b;
531     int di;
532     a = 0;
533     b = r;
534     di = 3 - (r << 1);
535     while (a <= b)
536     {
537         lcd_draw_point(x0 - b, y0 - a);
538         lcd_draw_point(x0 + b, y0 - a);
539         lcd_draw_point(x0 - a, y0 + b);
540         lcd_draw_point(x0 - b, y0 - a);
541         lcd_draw_point(x0 - a, y0 - b);
542         lcd_draw_point(x0 + b, y0 + a);
543         lcd_draw_point(x0 + a, y0 - b);
544         lcd_draw_point(x0 + a, y0 + b);
545         lcd_draw_point(x0 - b, y0 + a);
546         a++;
547         //Bresenham
548         if (di < 0)di += 4 * a + 6;
549         else
550         {
551             di += 10 + 4 * (a - b);
552             b--;
553         }
554         lcd_draw_point(x0 + a, y0 + b);
555     }
556 }
557 
lcd_show_char(rt_uint16_t x,rt_uint16_t y,rt_uint8_t data,rt_uint32_t size)558 static void lcd_show_char(rt_uint16_t x, rt_uint16_t y, rt_uint8_t data, rt_uint32_t size)
559 {
560     rt_uint8_t temp;
561     rt_uint8_t num = 0;;
562     rt_uint8_t pos, t;
563     rt_uint16_t colortemp = FORE_COLOR;
564     rt_uint8_t *font_buf = RT_NULL;
565 
566     if (x > LCD_W - size / 2 || y > LCD_H - size)return;
567 
568     data = data - ' ';
569 #ifdef ASC2_1608
570     if (size == 16)
571     {
572         lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);//(x,y,x+8-1,y+16-1)
573 
574         font_buf = (rt_uint8_t *)rt_malloc(size * size);
575         if (!font_buf)
576         {
577             /* fast show char */
578             for (pos = 0; pos < size * (size / 2) / 8; pos++)
579             {
580                 temp = asc2_1608[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
581                 for (t = 0; t < 8; t++)
582                 {
583                     if (temp & 0x80)colortemp = FORE_COLOR;
584                     else colortemp = BACK_COLOR;
585                     lcd_write_half_word(colortemp);
586                     temp <<= 1;
587                 }
588             }
589         }
590         else
591         {
592             for (pos = 0; pos < size * (size / 2) / 8; pos++)
593             {
594                 temp = asc2_1608[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
595                 for (t = 0; t < 8; t++)
596                 {
597                     if (temp & 0x80)colortemp = FORE_COLOR;
598                     else colortemp = BACK_COLOR;
599                     font_buf[2 * (8 * pos + t)] = colortemp >> 8;
600                     font_buf[2 * (8 * pos + t) + 1] = colortemp;
601                     temp <<= 1;
602                 }
603             }
604             rt_pin_write(LCD_DC_PIN, PIN_HIGH);
605             rt_spi_send(spi_dev_lcd, font_buf, size * size);
606             rt_free(font_buf);
607         }
608     }
609     else
610 #endif
611 
612 #ifdef ASC2_2412
613         if (size == 24)
614         {
615             lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);
616 
617             font_buf = (rt_uint8_t *)rt_malloc(size * size);
618             if (!font_buf)
619             {
620                 /* fast show char */
621                 for (pos = 0; pos < (size * 16) / 8; pos++)
622                 {
623                     temp = asc2_2412[(rt_uint16_t)data * (size * 16) / 8 + pos];
624                     if (pos % 2 == 0)
625                     {
626                         num = 8;
627                     }
628                     else
629                     {
630                         num = 4;
631                     }
632 
633                     for (t = 0; t < num; t++)
634                     {
635                         if (temp & 0x80)colortemp = FORE_COLOR;
636                         else colortemp = BACK_COLOR;
637                         lcd_write_half_word(colortemp);
638                         temp <<= 1;
639                     }
640                 }
641             }
642             else
643             {
644                 for (pos = 0; pos < (size * 16) / 8; pos++)
645                 {
646                     temp = asc2_2412[(rt_uint16_t)data * (size * 16) / 8 + pos];
647                     if (pos % 2 == 0)
648                     {
649                         num = 8;
650                     }
651                     else
652                     {
653                         num = 4;
654                     }
655 
656                     for (t = 0; t < num; t++)
657                     {
658                         if (temp & 0x80)colortemp = FORE_COLOR;
659                         else colortemp = BACK_COLOR;
660                         if (num == 8)
661                         {
662                             font_buf[2 * (12 * (pos / 2) + t)] = colortemp >> 8;
663                             font_buf[2 * (12 * (pos / 2) + t) + 1] = colortemp;
664                         }
665                         else
666                         {
667                             font_buf[2 * (8 + 12 * (pos / 2) + t)] = colortemp >> 8;
668                             font_buf[2 * (8 + 12 * (pos / 2) + t) + 1] = colortemp;
669                         }
670                         temp <<= 1;
671                     }
672                 }
673                 rt_pin_write(LCD_DC_PIN, PIN_HIGH);
674                 rt_spi_send(spi_dev_lcd, font_buf, size * size);
675                 rt_free(font_buf);
676             }
677         }
678         else
679 #endif
680 
681 #ifdef ASC2_3216
682             if (size == 32)
683             {
684                 lcd_address_set(x, y, x + size / 2 - 1, y + size - 1);
685 
686                 font_buf = (rt_uint8_t *)rt_malloc(size * size);
687                 if (!font_buf)
688                 {
689                     /* fast show char */
690                     for (pos = 0; pos < size * (size / 2) / 8; pos++)
691                     {
692                         temp = asc2_3216[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
693                         for (t = 0; t < 8; t++)
694                         {
695                             if (temp & 0x80)colortemp = FORE_COLOR;
696                             else colortemp = BACK_COLOR;
697                             lcd_write_half_word(colortemp);
698                             temp <<= 1;
699                         }
700                     }
701                 }
702                 else
703                 {
704                     for (pos = 0; pos < size * (size / 2) / 8; pos++)
705                     {
706                         temp = asc2_3216[(rt_uint16_t)data * size * (size / 2) / 8 + pos];
707                         for (t = 0; t < 8; t++)
708                         {
709                             if (temp & 0x80)colortemp = FORE_COLOR;
710                             else colortemp = BACK_COLOR;
711                             font_buf[2 * (8 * pos + t)] = colortemp >> 8;
712                             font_buf[2 * (8 * pos + t) + 1] = colortemp;
713                             temp <<= 1;
714                         }
715                     }
716                     rt_pin_write(LCD_DC_PIN, PIN_HIGH);
717                     rt_spi_send(spi_dev_lcd, font_buf, size * size);
718                     rt_free(font_buf);
719                 }
720             }
721             else
722 #endif
723             {
724                 LOG_E("There is no any define ASC2_1208 && ASC2_2412 && ASC2_2416 && ASC2_3216 !");
725             }
726 }
727 
728 /**
729  * display the number on the lcd.
730  *
731  * @param   x       x position
732  * @param   y       y position
733  * @param   num     number
734  * @param   len     length of number
735  * @param   size    size of font
736  *
737  * @return  void
738  */
lcd_show_num(rt_uint16_t x,rt_uint16_t y,rt_uint32_t num,rt_uint8_t len,rt_uint32_t size)739 void lcd_show_num(rt_uint16_t x, rt_uint16_t y, rt_uint32_t num, rt_uint8_t len, rt_uint32_t size)
740 {
741     lcd_show_string(x, y, size, "%d", num);
742 }
743 
744 /**
745  * display the string on the lcd.
746  *
747  * @param   x       x position
748  * @param   y       y position
749  * @param   size    size of font
750  * @param   p       the string to be display
751  *
752  * @return   0: display success
753  *          -1: size of font is not support
754  */
lcd_show_string(rt_uint16_t x,rt_uint16_t y,rt_uint32_t size,const char * fmt,...)755 rt_err_t lcd_show_string(rt_uint16_t x, rt_uint16_t y, rt_uint32_t size, const char *fmt, ...)
756 {
757 #define LCD_STRING_BUF_LEN 128
758 
759     va_list args;
760     rt_uint8_t buf[LCD_STRING_BUF_LEN] = {0};
761     rt_uint8_t *p = RT_NULL;
762 
763     if (size != 16 && size != 24 && size != 32)
764     {
765         LOG_E("font size(%d) is not support!", size);
766         return -RT_ERROR;
767     }
768 
769     va_start(args, fmt);
770     rt_vsnprintf((char *)buf, 100, (const char *)fmt, args);
771     va_end(args);
772 
773     p = buf;
774     while (*p != '\0')
775     {
776         if (x > LCD_W - size / 2)
777         {
778             x = 0;
779             y += size;
780         }
781         if (y > LCD_H - size)
782         {
783             y = x = 0;
784             lcd_clear(RED);
785         }
786         lcd_show_char(x, y, *p, size);
787         x += size / 2;
788         p++;
789     }
790 
791     return RT_EOK;
792 }
793 
794 /**
795  * display the image on the lcd.
796  *
797  * @param   x       x position
798  * @param   y       y position
799  * @param   length  length of image
800  * @param   wide    wide of image
801  * @param   p       image
802  *
803  * @return   0: display success
804  *          -1: the image is too large
805  */
lcd_show_image(rt_uint16_t x,rt_uint16_t y,rt_uint16_t length,rt_uint16_t wide,const rt_uint8_t * p)806 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)
807 {
808     RT_ASSERT(p);
809 
810     if (x + length > LCD_W || y + wide > LCD_H)
811     {
812         return -RT_ERROR;
813     }
814 
815     lcd_address_set(x, y, x + length - 1, y + wide - 1);
816 
817     rt_pin_write(LCD_DC_PIN, PIN_HIGH);
818     rt_spi_send(spi_dev_lcd, p, length * wide * 2);
819 
820     return RT_EOK;
821 }
822