monitor.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /**
  2. * @file monitor.c
  3. *
  4. */
  5. /*********************
  6. * INCLUDES
  7. *********************/
  8. #include "monitor.h"
  9. #if USE_MONITOR
  10. #include <stdlib.h>
  11. #include <stdbool.h>
  12. #include <unistd.h>
  13. #include <string.h>
  14. #include <SDL2/SDL.h>
  15. #include "lvgl/lv_core/lv_vdb.h"
  16. /*********************
  17. * DEFINES
  18. *********************/
  19. #define SDL_REFR_PERIOD 50 /*ms*/
  20. /**********************
  21. * TYPEDEFS
  22. **********************/
  23. /**********************
  24. * STATIC PROTOTYPES
  25. **********************/
  26. static int sdl_refr(void * param);
  27. /***********************
  28. * GLOBAL PROTOTYPES
  29. ***********************/
  30. #if USE_MOUSE
  31. void mouse_handler(SDL_Event *event);
  32. #endif
  33. #if USE_KEYBOARD
  34. void keyboard_handler(SDL_Event *event);
  35. #endif
  36. /**********************
  37. * STATIC VARIABLES
  38. **********************/
  39. static SDL_Window * window;
  40. static SDL_Renderer * renderer;
  41. static SDL_Texture * texture;
  42. static uint32_t tft_fb[MONITOR_HOR_RES * MONITOR_VER_RES];
  43. static volatile bool sdl_inited = false;
  44. static volatile bool sdl_refr_qry = false;
  45. static volatile bool sdl_quit_qry = false;
  46. int quit_filter (void *userdata, SDL_Event * event);
  47. /**********************
  48. * MACROS
  49. **********************/
  50. /**********************
  51. * GLOBAL FUNCTIONS
  52. **********************/
  53. /**
  54. * Initialize the monitor
  55. */
  56. void monitor_init(void)
  57. {
  58. SDL_CreateThread(sdl_refr, "sdl_refr", NULL);
  59. while(sdl_inited == false); /*Wait until 'sdl_refr' initializes the SDL*/
  60. }
  61. /**
  62. * Flush a buffer to the display. Calls 'lv_flush_ready()' when finished
  63. * @param x1 left coordinate
  64. * @param y1 top coordinate
  65. * @param x2 right coordinate
  66. * @param y2 bottom coordinate
  67. * @param color_p array of colors to be flushed
  68. */
  69. void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t *color_p)
  70. {
  71. /*Return if the area is out the screen*/
  72. if(x2 < 0 || y2 < 0 || x1 > MONITOR_HOR_RES - 1 || y1 > MONITOR_VER_RES - 1) {
  73. lv_flush_ready();
  74. return;
  75. }
  76. int32_t y;
  77. #if LV_COLOR_DEPTH != 24
  78. int32_t x;
  79. for(y = y1; y <= y2; y++) {
  80. for(x = x1; x <= x2; x++) {
  81. tft_fb[y * MONITOR_HOR_RES + x] = lv_color_to24(*color_p) | 0xFF000000;
  82. color_p++;
  83. }
  84. }
  85. #else
  86. uint32_t w = x2 - x1 + 1;
  87. for(y = y1; y <= y2; y++) {
  88. memcpy(&tft_fb[y * MONITOR_HOR_RES + x1], color_p, w * sizeof(lv_color_t));
  89. color_p += w;
  90. }
  91. #endif
  92. sdl_refr_qry = true;
  93. /*IMPORTANT! It must be called to tell the system the flush is ready*/
  94. lv_flush_ready();
  95. }
  96. /**
  97. * Fill out the marked area with a color
  98. * @param x1 left coordinate
  99. * @param y1 top coordinate
  100. * @param x2 right coordinate
  101. * @param y2 bottom coordinate
  102. * @param color fill color
  103. */
  104. void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2, lv_color_t color)
  105. {
  106. /*Return if the area is out the screen*/
  107. if(x2 < 0) return;
  108. if(y2 < 0) return;
  109. if(x1 > MONITOR_HOR_RES - 1) return;
  110. if(y1 > MONITOR_VER_RES - 1) return;
  111. /*Truncate the area to the screen*/
  112. int32_t act_x1 = x1 < 0 ? 0 : x1;
  113. int32_t act_y1 = y1 < 0 ? 0 : y1;
  114. int32_t act_x2 = x2 > MONITOR_HOR_RES - 1 ? MONITOR_HOR_RES - 1 : x2;
  115. int32_t act_y2 = y2 > MONITOR_VER_RES - 1 ? MONITOR_VER_RES - 1 : y2;
  116. int32_t x;
  117. int32_t y;
  118. uint32_t color24 = lv_color_to24(color);
  119. for(x = act_x1; x <= act_x2; x++) {
  120. for(y = act_y1; y <= act_y2; y++) {
  121. tft_fb[y * MONITOR_HOR_RES + x] = color24 | 0xFF000000;
  122. }
  123. }
  124. sdl_refr_qry = true;
  125. }
  126. /**
  127. * Put a color map to the marked area
  128. * @param x1 left coordinate
  129. * @param y1 top coordinate
  130. * @param x2 right coordinate
  131. * @param y2 bottom coordinate
  132. * @param color_p an array of colors
  133. */
  134. void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t * color_p)
  135. {
  136. /*Return if the area is out the screen*/
  137. if(x2 < 0) return;
  138. if(y2 < 0) return;
  139. if(x1 > MONITOR_HOR_RES - 1) return;
  140. if(y1 > MONITOR_VER_RES - 1) return;
  141. /*Truncate the area to the screen*/
  142. int32_t act_x1 = x1 < 0 ? 0 : x1;
  143. int32_t act_y1 = y1 < 0 ? 0 : y1;
  144. int32_t act_x2 = x2 > MONITOR_HOR_RES - 1 ? MONITOR_HOR_RES - 1 : x2;
  145. int32_t act_y2 = y2 > MONITOR_VER_RES - 1 ? MONITOR_VER_RES - 1 : y2;
  146. int32_t x;
  147. int32_t y;
  148. for(y = act_y1; y <= act_y2; y++) {
  149. for(x = act_x1; x <= act_x2; x++) {
  150. tft_fb[y * MONITOR_HOR_RES + x] = lv_color_to24(*color_p) | 0xFF000000;
  151. color_p++;
  152. }
  153. color_p += x2 - act_x2;
  154. }
  155. sdl_refr_qry = true;
  156. }
  157. /**********************
  158. * STATIC FUNCTIONS
  159. **********************/
  160. /**
  161. * SDL main thread. All SDL related task have to be handled here!
  162. * It initializes SDL, handles drawing and the mouse.
  163. */
  164. static int sdl_refr(void * param)
  165. {
  166. (void)param;
  167. /*Initialize the SDL*/
  168. SDL_Init(SDL_INIT_VIDEO);
  169. SDL_SetEventFilter(quit_filter, NULL);
  170. window = SDL_CreateWindow("TFT Simulator",
  171. SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
  172. MONITOR_HOR_RES, MONITOR_VER_RES, 0); /*last param. SDL_WINDOW_BORDERLESS to hide borders*/
  173. renderer = SDL_CreateRenderer(window, -1, 0);
  174. texture = SDL_CreateTexture(renderer,
  175. SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, MONITOR_HOR_RES, MONITOR_VER_RES);
  176. /*Initialize the frame buffer to gray (77 is an empirical value) */
  177. memset(tft_fb, 77, MONITOR_HOR_RES * MONITOR_VER_RES * sizeof(uint32_t));
  178. SDL_UpdateTexture(texture, NULL, tft_fb, MONITOR_HOR_RES * sizeof(uint32_t));
  179. sdl_refr_qry = true;
  180. sdl_inited = true;
  181. /*Run until quit event not arrives*/
  182. while(sdl_quit_qry == false) {
  183. /*Refresh handling*/
  184. if(sdl_refr_qry != false) {
  185. sdl_refr_qry = false;
  186. SDL_UpdateTexture(texture, NULL, tft_fb, MONITOR_HOR_RES * sizeof(uint32_t));
  187. SDL_RenderClear(renderer);
  188. SDL_RenderCopy(renderer, texture, NULL, NULL);
  189. SDL_RenderPresent(renderer);
  190. }
  191. SDL_Event event;
  192. while(SDL_PollEvent(&event)) {
  193. #if USE_MOUSE != 0
  194. mouse_handler(&event);
  195. #endif
  196. #if USE_KEYBOARD
  197. keyboard_handler(&event);
  198. #endif
  199. }
  200. /*Sleep some time*/
  201. SDL_Delay(SDL_REFR_PERIOD);
  202. }
  203. SDL_DestroyTexture(texture);
  204. SDL_DestroyRenderer(renderer);
  205. SDL_DestroyWindow(window);
  206. SDL_Quit();
  207. exit(0);
  208. return 0;
  209. }
  210. int quit_filter (void *userdata, SDL_Event * event)
  211. {
  212. (void)userdata;
  213. if(event->type == SDL_QUIT) {
  214. sdl_quit_qry = true;
  215. }
  216. return 1;
  217. }
  218. #endif