lcd_console.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. * 2020-11-09 bigmagic first version
  9. */
  10. #include "lcd_console.h"
  11. #include "lcd_font_20.h"
  12. #define LCD_CONSOLE_FLUSH_NOW 1
  13. #define CONSOLE_NAME "hdmi"
  14. #define COLOR_DELTA 0.05
  15. #ifndef LCD_CONSOLE_FLUSH_NOW
  16. static rt_thread_t console_flush_thread_tid = RT_NULL;
  17. #define CONSOLE_FLUSH_THREAD_STACK_SIZE (1024)
  18. #define CONSOLE_FLUSH_THREAD_PRIORITY (20)
  19. #define CONSOLE_FLUSH_THREAD_TIMESLICE (10)
  20. #define LCD_CONSOLE_DELAY (100) //100ms
  21. #endif
  22. static rt_device_t console_dev = RT_NULL;
  23. static fb_t console_fb;
  24. static rt_uint8_t* virt_buffer;
  25. static rt_uint32_t CHAR_W = 8;
  26. static rt_uint32_t CHAR_H = 20;
  27. static int prev_x_offset = 0;
  28. static void newline(fb_t* fb)
  29. {
  30. uint8_t* to;
  31. uint8_t* from;
  32. int i;
  33. fb->y++;
  34. fb->x = 5 * fb->depth;
  35. if (fb->y == (fb->height / CHAR_H))
  36. {
  37. to = (uint8_t*) fb->vaddr;
  38. from = to + (CHAR_H * fb->pitch);
  39. for (i = 0; i < ((fb->height - CHAR_H) * fb->pitch); i++)
  40. {
  41. *to++ = *from++;
  42. }
  43. if(fb->depth >= 3)
  44. {
  45. uint32_t *addr_32bit = (uint32_t*) (fb->vaddr) + (fb->height - CHAR_H) * fb->width;
  46. for (i = 0; i < (CHAR_H * fb->width); i++)
  47. {
  48. *addr_32bit++ = fb->back;
  49. }
  50. }
  51. else
  52. {
  53. uint16_t *addr_16bit = (uint16_t*) (fb->vaddr) + (fb->height - CHAR_H) * fb->width;
  54. for (i = 0; i < (CHAR_H * fb->width); i++)
  55. {
  56. *addr_16bit++ = fb->back;
  57. }
  58. }
  59. fb->y = fb->y - 1;
  60. }
  61. }
  62. static void fb_draw_char(fb_t *fb, char s)
  63. {
  64. unsigned char* addr = (unsigned char*) fb->vaddr;
  65. unsigned char *glyph = (unsigned char *)lcd_console_font_dejavu_20_glyph_bitmap + lcd_console_font_dejavu_20_glyph_dsc[s - 32].glyph_index;
  66. CHAR_W = lcd_console_font_dejavu_20_glyph_dsc[s - 32].w_px;
  67. fb->x = fb->x + prev_x_offset * fb->depth;
  68. int i, j, line, mask, bytesperline = (CHAR_W + 7) / 8;
  69. int kk = (bytesperline) * 8;
  70. prev_x_offset = CHAR_W + 2;
  71. // calculate the offset on screen
  72. int offs = (fb->y * CHAR_H * fb->pitch) + fb->x;
  73. // display a character
  74. for (j = 0; j < CHAR_H; j++)
  75. {
  76. // display one row
  77. line = offs;
  78. mask = 1;
  79. mask = 0x80;
  80. for (i = 0; i < kk; i++)
  81. {
  82. if(fb->depth >= 3)
  83. {
  84. *((unsigned int*) (addr + line)) = ((int) *(glyph + ((i)/8)) * 1) & mask ? fb->fore : fb->back;
  85. }
  86. else
  87. {
  88. *((unsigned short*) (addr + line)) = ((int) *(glyph + ((i)/8)) * 1) & mask ? fb->fore : fb->back;
  89. }
  90. mask >>= 1;
  91. if(mask == 0)
  92. {
  93. mask = 0x80;
  94. }
  95. line += fb->depth;
  96. }
  97. // adjust to next line
  98. glyph += bytesperline;
  99. offs += fb->pitch;
  100. }
  101. }
  102. void fb_print(char *s)
  103. {
  104. fb_t *fb = &console_fb;
  105. // draw next character if it's not zero
  106. while (*s)
  107. {
  108. // handle carrige return
  109. if (*s == '\r')
  110. {
  111. fb->x = 5 * fb->depth;
  112. }
  113. else if (*s == '\n')
  114. {
  115. newline(fb);
  116. }
  117. else if (*s == '\t')
  118. {
  119. //tab is 8 spaces
  120. if((fb->x + 8 * fb->depth) < (fb->width) * fb->depth)
  121. {
  122. fb->x = fb->x + 8 * fb->depth;
  123. }
  124. }
  125. else if (*s == '\b')
  126. {
  127. if (fb->x > 5 * fb->depth)
  128. {
  129. fb->x = fb->x - prev_x_offset * fb->depth;
  130. fb_draw_char(fb, ' ');
  131. }
  132. }
  133. else if((fb->x + prev_x_offset * fb->depth + 5 * fb->depth) >= (fb->width * fb->depth))
  134. {
  135. newline(fb);
  136. fb_draw_char(fb, *s);
  137. }
  138. else
  139. {
  140. fb_draw_char(fb, *s);
  141. }
  142. s++;
  143. }
  144. #ifdef LCD_CONSOLE_FLUSH_NOW
  145. rt_memcpy((void *)fb->paddr, (void *)fb->vaddr, fb->size);
  146. if(console_dev != RT_NULL)
  147. {
  148. rt_device_control(console_dev,RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
  149. }
  150. #endif
  151. }
  152. #ifndef LCD_CONSOLE_FLUSH_NOW
  153. void lcd_console_task_entry(void *param)
  154. {
  155. fb_t *fb = (fb_t *)param;
  156. while (1)
  157. {
  158. rt_memcpy((void *)fb->paddr, (void *)fb->vaddr, fb->size);
  159. if(console_dev != RT_NULL)
  160. {
  161. rt_device_control(console_dev,RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
  162. }
  163. rt_thread_mdelay(LCD_CONSOLE_DELAY);
  164. }
  165. }
  166. #endif
  167. int lcd_console_init(void)
  168. {
  169. struct rt_device_graphic_info info;
  170. console_dev = rt_device_find(CONSOLE_NAME);
  171. if(console_dev == RT_NULL)
  172. {
  173. rt_kprintf("no console dev!\n");
  174. return 0;
  175. }
  176. if(console_dev->ref_count >= 1)
  177. {
  178. rt_kprintf("lcd console has open!\n");
  179. return 0;
  180. }
  181. rt_device_open(console_dev,RT_DEVICE_OFLAG_RDWR);
  182. rt_device_control(console_dev, RTGRAPHIC_CTRL_GET_INFO, &info);
  183. virt_buffer = (rt_uint8_t* )rt_malloc(info.width * info.height * (info.bits_per_pixel/8));
  184. rt_memset(virt_buffer, 0 , info.width * info.height * (info.bits_per_pixel/8));
  185. console_fb.width = info.width;
  186. console_fb.height = info.height;
  187. console_fb.pitch = info.width * (info.bits_per_pixel/8);
  188. console_fb.vaddr = (rt_uint32_t)virt_buffer;
  189. console_fb.paddr = (rt_uint32_t)info.framebuffer;
  190. console_fb.size = info.width * info.height * (info.bits_per_pixel/8);
  191. console_fb.depth = info.bits_per_pixel/8;
  192. console_fb.x = 0;
  193. console_fb.y = 0;
  194. if(console_fb.depth >= 3)
  195. {
  196. console_fb.fore = CONSOLE_WHITE_32;
  197. console_fb.back = CONSOLE_BLACK_32;
  198. }
  199. else
  200. {
  201. console_fb.fore = CONSOLE_WHITE_16;
  202. console_fb.back = CONSOLE_BLACK_16;
  203. }
  204. #ifndef LCD_CONSOLE_FLUSH_NOW
  205. console_flush_thread_tid = rt_thread_create("lcd_console", lcd_console_task_entry, (void *)&console_fb,
  206. CONSOLE_FLUSH_THREAD_STACK_SIZE,
  207. CONSOLE_FLUSH_THREAD_PRIORITY, CONSOLE_FLUSH_THREAD_TIMESLICE);
  208. if (console_flush_thread_tid != RT_NULL)
  209. rt_thread_startup(console_flush_thread_tid);
  210. #endif
  211. /*
  212. * note:
  213. * if serial console and lcd console together
  214. * you can add /src/kservice.c:rt_kprintf
  215. * #ifdef USING_LCD_CONSOLE
  216. * fb_print((char*)rt_log_buf);
  217. * #endif
  218. *
  219. * remove rt_console_set_device(CONSOLE_NAME);
  220. */
  221. rt_console_set_device(CONSOLE_NAME);
  222. rt_show_version();//show rt-thread logo
  223. return 0;
  224. }
  225. INIT_APP_EXPORT(lcd_console_init);