test_spi_lcd_panel.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "sdkconfig.h"
  4. #include "unity.h"
  5. #include "test_utils.h"
  6. #include "driver/spi_master.h"
  7. #include "driver/gpio.h"
  8. #include "esp_lcd_panel_io.h"
  9. #include "esp_lcd_panel_vendor.h"
  10. #include "esp_lcd_panel_ops.h"
  11. #include "esp_system.h"
  12. #include "soc/soc_caps.h"
  13. #include "test_spi_board.h"
  14. #define TEST_SPI_HOST_ID (1)
  15. #define TEST_LCD_PIXEL_CLOCK_HZ (20 * 1000 * 1000) // 20MHz
  16. static void lcd_initialize_spi(esp_lcd_panel_io_handle_t *io_handle, esp_lcd_panel_io_color_trans_done_cb_t on_color_trans_done, void *user_ctx, int cmd_bits, int param_bits, bool oct_mode)
  17. {
  18. gpio_config_t bk_gpio_config = {
  19. .mode = GPIO_MODE_OUTPUT,
  20. .pin_bit_mask = 1ULL << TEST_LCD_BK_LIGHT_GPIO
  21. };
  22. TEST_ESP_OK(gpio_config(&bk_gpio_config));
  23. spi_bus_config_t buscfg = {
  24. .sclk_io_num = TEST_LCD_PCLK_GPIO,
  25. .mosi_io_num = TEST_LCD_DATA0_GPIO,
  26. .miso_io_num = -1,
  27. .quadwp_io_num = -1,
  28. .quadhd_io_num = -1,
  29. .max_transfer_sz = TEST_LCD_H_RES * TEST_LCD_V_RES * sizeof(uint16_t)
  30. };
  31. if (oct_mode) {
  32. buscfg.data1_io_num = TEST_LCD_DATA1_GPIO;
  33. buscfg.data2_io_num = TEST_LCD_DATA2_GPIO;
  34. buscfg.data3_io_num = TEST_LCD_DATA3_GPIO;
  35. buscfg.data4_io_num = TEST_LCD_DATA4_GPIO;
  36. buscfg.data5_io_num = TEST_LCD_DATA5_GPIO;
  37. buscfg.data6_io_num = TEST_LCD_DATA6_GPIO;
  38. buscfg.data7_io_num = TEST_LCD_DATA7_GPIO;
  39. buscfg.flags = SPICOMMON_BUSFLAG_OCTAL;
  40. }
  41. TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST_ID, &buscfg, SPI_DMA_CH_AUTO));
  42. esp_lcd_panel_io_spi_config_t io_config = {
  43. .dc_gpio_num = TEST_LCD_DC_GPIO,
  44. .cs_gpio_num = TEST_LCD_CS_GPIO,
  45. .pclk_hz = TEST_LCD_PIXEL_CLOCK_HZ,
  46. .spi_mode = 0,
  47. .trans_queue_depth = 10,
  48. .lcd_cmd_bits = cmd_bits,
  49. .lcd_param_bits = param_bits,
  50. .on_color_trans_done = on_color_trans_done,
  51. .user_ctx = user_ctx
  52. };
  53. if (oct_mode) {
  54. io_config.flags.octal_mode = 1;
  55. io_config.spi_mode = 3;
  56. }
  57. TEST_ESP_OK(esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)TEST_SPI_HOST_ID, &io_config, io_handle));
  58. }
  59. static void lcd_panel_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle)
  60. {
  61. #define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
  62. uint8_t *img = heap_caps_malloc(TEST_IMG_SIZE, MALLOC_CAP_DMA);
  63. TEST_ASSERT_NOT_NULL(img);
  64. // turn off backlight
  65. gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 0);
  66. esp_lcd_panel_reset(panel_handle);
  67. esp_lcd_panel_init(panel_handle);
  68. esp_lcd_panel_invert_color(panel_handle, true);
  69. // the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
  70. esp_lcd_panel_set_gap(panel_handle, 0, 20);
  71. // turn on backlight
  72. gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
  73. for (int i = 0; i < 200; i++) {
  74. uint8_t color_byte = esp_random() & 0xFF;
  75. int x_start = esp_random() % (TEST_LCD_H_RES - 100);
  76. int y_start = esp_random() % (TEST_LCD_V_RES - 100);
  77. memset(img, color_byte, TEST_IMG_SIZE);
  78. esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
  79. }
  80. // turn off screen
  81. esp_lcd_panel_disp_off(panel_handle, true);
  82. TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
  83. TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
  84. TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
  85. TEST_ESP_OK(gpio_reset_pin(TEST_LCD_BK_LIGHT_GPIO));
  86. free(img);
  87. #undef TEST_IMG_SIZE
  88. }
  89. TEST_CASE("lcd panel spi io test", "[lcd]")
  90. {
  91. esp_lcd_panel_io_handle_t io_handle = NULL;
  92. lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, false);
  93. esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0);
  94. esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) {
  95. 0x11, 0x22, 0x33
  96. }, 3);
  97. esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0);
  98. TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
  99. TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
  100. lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, false);
  101. esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0);
  102. esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) {
  103. 0x11, 0x22, 0x33
  104. }, 6);
  105. esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0);
  106. TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
  107. TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
  108. #if SOC_SPI_SUPPORT_OCT
  109. lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, true);
  110. esp_lcd_panel_io_tx_param(io_handle, 0x1A, NULL, 0);
  111. esp_lcd_panel_io_tx_param(io_handle, 0x1B, (uint8_t[]) {
  112. 0x11, 0x22, 0x33
  113. }, 3);
  114. esp_lcd_panel_io_tx_param(io_handle, 0x1C, NULL, 0);
  115. TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
  116. TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
  117. lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, true);
  118. esp_lcd_panel_io_tx_param(io_handle, 0x1A01, NULL, 0);
  119. esp_lcd_panel_io_tx_param(io_handle, 0x1B02, (uint16_t[]) {
  120. 0x11, 0x22, 0x33
  121. }, 6);
  122. esp_lcd_panel_io_tx_param(io_handle, 0x1C03, NULL, 0);
  123. TEST_ESP_OK(esp_lcd_panel_io_del(io_handle));
  124. TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST_ID));
  125. #endif // SOC_SPI_SUPPORT_OCT
  126. }
  127. #if SOC_SPI_SUPPORT_OCT
  128. TEST_CASE("lcd panel with 8-line spi interface (st7789)", "[lcd]")
  129. {
  130. esp_lcd_panel_io_handle_t io_handle = NULL;
  131. esp_lcd_panel_handle_t panel_handle = NULL;
  132. lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, true);
  133. esp_lcd_panel_dev_config_t panel_config = {
  134. .reset_gpio_num = TEST_LCD_RST_GPIO,
  135. .color_space = ESP_LCD_COLOR_SPACE_RGB,
  136. .bits_per_pixel = 16,
  137. };
  138. TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
  139. lcd_panel_test(io_handle, panel_handle);
  140. }
  141. TEST_CASE("lcd panel with 8-line spi interface (nt35510)", "[lcd]")
  142. {
  143. esp_lcd_panel_io_handle_t io_handle = NULL;
  144. esp_lcd_panel_handle_t panel_handle = NULL;
  145. lcd_initialize_spi(&io_handle, NULL, NULL, 16, 16, true);
  146. esp_lcd_panel_dev_config_t panel_config = {
  147. .reset_gpio_num = TEST_LCD_RST_GPIO,
  148. .color_space = ESP_LCD_COLOR_SPACE_RGB,
  149. .bits_per_pixel = 16,
  150. };
  151. TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
  152. lcd_panel_test(io_handle, panel_handle);
  153. }
  154. #endif // SOC_SPI_SUPPORT_OCT
  155. TEST_CASE("lcd panel with 1-line spi interface (st7789)", "[lcd]")
  156. {
  157. esp_lcd_panel_io_handle_t io_handle = NULL;
  158. esp_lcd_panel_handle_t panel_handle = NULL;
  159. lcd_initialize_spi(&io_handle, NULL, NULL, 8, 8, false);
  160. esp_lcd_panel_dev_config_t panel_config = {
  161. .reset_gpio_num = TEST_LCD_RST_GPIO,
  162. .color_space = ESP_LCD_COLOR_SPACE_RGB,
  163. .bits_per_pixel = 16,
  164. };
  165. TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
  166. lcd_panel_test(io_handle, panel_handle);
  167. }
  168. // The following test shows a porting example of LVGL GUI library
  169. // To run the LVGL tests, you need to clone the LVGL library into components directory firstly
  170. #if CONFIG_LV_USE_USER_DATA
  171. #include "test_lvgl_port.h"
  172. static bool notify_lvgl_ready_to_flush(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx)
  173. {
  174. lv_disp_t *disp = *(lv_disp_t **)user_ctx;
  175. lv_disp_flush_ready(&disp->driver);
  176. return false;
  177. }
  178. static void lvgl_gui_test(esp_lcd_panel_io_handle_t io_handle, esp_lcd_panel_handle_t panel_handle, lv_disp_t **disp)
  179. {
  180. // initialize LVGL graphics library
  181. lv_init();
  182. // turn off backlight
  183. gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 0);
  184. esp_lcd_panel_reset(panel_handle);
  185. esp_lcd_panel_init(panel_handle);
  186. esp_lcd_panel_invert_color(panel_handle, true);
  187. // the gap is LCD panel specific, even panels with the same driver IC, can have different gap value
  188. esp_lcd_panel_set_gap(panel_handle, 0, 20);
  189. // turn on backlight
  190. gpio_set_level(TEST_LCD_BK_LIGHT_GPIO, 1);
  191. test_lvgl_task_loop(panel_handle, TEST_LCD_H_RES, TEST_LCD_V_RES, disp);
  192. }
  193. #if SOC_SPI_SUPPORT_OCT
  194. TEST_CASE("lvgl gui with 8-line spi interface (st7789)", "[lcd][lvgl][ignore]")
  195. {
  196. lv_disp_t *disp = NULL;
  197. esp_lcd_panel_io_handle_t io_handle = NULL;
  198. esp_lcd_panel_handle_t panel_handle = NULL;
  199. lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 8, 8, true);
  200. esp_lcd_panel_dev_config_t panel_config = {
  201. .reset_gpio_num = TEST_LCD_RST_GPIO,
  202. .color_space = ESP_LCD_COLOR_SPACE_RGB,
  203. .bits_per_pixel = 16,
  204. };
  205. TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
  206. lvgl_gui_test(io_handle, panel_handle, &disp);
  207. }
  208. TEST_CASE("lvgl gui with 8-line spi interface (nt35510)", "[lcd][lvgl][ignore]")
  209. {
  210. lv_disp_t *disp = NULL;
  211. esp_lcd_panel_io_handle_t io_handle = NULL;
  212. esp_lcd_panel_handle_t panel_handle = NULL;
  213. lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 16, 16, true);
  214. esp_lcd_panel_dev_config_t panel_config = {
  215. .reset_gpio_num = TEST_LCD_RST_GPIO,
  216. .color_space = ESP_LCD_COLOR_SPACE_RGB,
  217. .bits_per_pixel = 16,
  218. };
  219. TEST_ESP_OK(esp_lcd_new_panel_nt35510(io_handle, &panel_config, &panel_handle));
  220. lvgl_gui_test(io_handle, panel_handle, &disp);
  221. }
  222. #endif // SOC_SPI_SUPPORT_OCT
  223. TEST_CASE("lvgl gui with 1-line spi interface (st7789)", "[lcd][lvgl][ignore]")
  224. {
  225. lv_disp_t *disp = NULL;
  226. esp_lcd_panel_io_handle_t io_handle = NULL;
  227. esp_lcd_panel_handle_t panel_handle = NULL;
  228. lcd_initialize_spi(&io_handle, notify_lvgl_ready_to_flush, &disp, 8, 8, false);
  229. esp_lcd_panel_dev_config_t panel_config = {
  230. .reset_gpio_num = TEST_LCD_RST_GPIO,
  231. .color_space = ESP_LCD_COLOR_SPACE_RGB,
  232. .bits_per_pixel = 16,
  233. };
  234. TEST_ESP_OK(esp_lcd_new_panel_st7789(io_handle, &panel_config, &panel_handle));
  235. lvgl_gui_test(io_handle, panel_handle, &disp);
  236. }
  237. #endif // CONFIG_LV_USE_USER_DATA