esp_lcd_panel_gc9301.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <stdlib.h>
  7. #include <sys/cdefs.h>
  8. #include "sdkconfig.h"
  9. #include <string.h>
  10. #if CONFIG_LCD_ENABLE_DEBUG_LOG
  11. // The local log level must be defined before including esp_log.h
  12. // Set the maximum log level for this source file
  13. #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
  14. #endif
  15. #include "freertos/FreeRTOS.h"
  16. #include "freertos/task.h"
  17. #include "esp_lcd_panel_interface.h"
  18. #include "esp_lcd_panel_io.h"
  19. #include "esp_lcd_panel_vendor.h"
  20. #include "esp_lcd_panel_ops.h"
  21. #include "esp_lcd_panel_commands.h"
  22. #include "driver/gpio.h"
  23. #include "esp_log.h"
  24. #include "esp_check.h"
  25. #include "esp_compiler.h"
  26. /* GC9309NA LCD controller driver for ESP-IDF
  27. * SPDX-FileCopyrightText: 2024 Your Name
  28. * SPDX-License-Identifier: Apache-2.0
  29. */
  30. #include "freertos/FreeRTOS.h"
  31. #include "freertos/task.h"
  32. #include "esp_lcd_panel_interface.h"
  33. #include "esp_lcd_panel_io.h"
  34. #include "esp_check.h"
  35. #include "driver/gpio.h"
  36. // GC9309NA Command Set
  37. #define GC9309NA_CMD_SLPIN 0x10
  38. #define GC9309NA_CMD_SLPOUT 0x11
  39. #define GC9309NA_CMD_INVOFF 0x20
  40. #define GC9309NA_CMD_INVON 0x21
  41. #define GC9309NA_CMD_DISPOFF 0x28
  42. #define GC9309NA_CMD_DISPON 0x29
  43. #define GC9309NA_CMD_CASET 0x2A
  44. #define GC9309NA_CMD_RASET 0x2B
  45. #define GC9309NA_CMD_RAMWR 0x2C
  46. #define GC9309NA_CMD_MADCTL 0x36
  47. #define GC9309NA_CMD_COLMOD 0x3A
  48. #define GC9309NA_CMD_TEOFF 0x34
  49. #define GC9309NA_CMD_TEON 0x35
  50. #define GC9309NA_CMD_WRDISBV 0x51
  51. #define GC9309NA_CMD_WRCTRLD 0x53
  52. // Manufacturer Commands
  53. #define GC9309NA_CMD_SETGAMMA1 0xF0
  54. #define GC9309NA_CMD_SETGAMMA2 0xF1
  55. #define GC9309NA_CMD_PWRCTRL1 0x67
  56. #define GC9309NA_CMD_PWRCTRL2 0x68
  57. #define GC9309NA_CMD_PWRCTRL3 0x66
  58. #define GC9309NA_CMD_PWRCTRL4 0xCA
  59. #define GC9309NA_CMD_PWRCTRL5 0xCB
  60. #define GC9309NA_CMD_DINVCTRL 0xB5
  61. #define GC9309NA_CMD_REG_ENABLE1 0xFE
  62. #define GC9309NA_CMD_REG_ENABLE2 0xEF
  63. // 自检模式颜色定义
  64. static const char *TAG = "lcd_panel.gc9309na";
  65. typedef struct {
  66. esp_lcd_panel_t base;
  67. esp_lcd_panel_io_handle_t io;
  68. int reset_gpio_num;
  69. bool reset_level;
  70. int x_gap;
  71. int y_gap;
  72. uint8_t madctl_val;
  73. uint8_t colmod_val;
  74. uint16_t te_scanline;
  75. uint8_t fb_bits_per_pixel;
  76. } gc9309na_panel_t;
  77. static esp_err_t panel_gc9309na_del(esp_lcd_panel_t *panel);
  78. static esp_err_t panel_gc9309na_reset(esp_lcd_panel_t *panel);
  79. static esp_err_t panel_gc9309na_init(esp_lcd_panel_t *panel);
  80. static esp_err_t panel_gc9309na_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data);
  81. static esp_err_t panel_gc9309na_invert_color(esp_lcd_panel_t *panel, bool invert_color_data);
  82. static esp_err_t panel_gc9309na_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y);
  83. static esp_err_t panel_gc9309na_swap_xy(esp_lcd_panel_t *panel, bool swap_axes);
  84. static esp_err_t panel_gc9309na_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap);
  85. static esp_err_t panel_gc9309na_disp_on_off(esp_lcd_panel_t *panel, bool off);
  86. static esp_err_t panel_gc9309na_sleep(esp_lcd_panel_t *panel, bool sleep);
  87. esp_err_t esp_lcd_new_panel_gc9309na(const esp_lcd_panel_io_handle_t io, const esp_lcd_panel_dev_config_t *panel_dev_config, esp_lcd_panel_handle_t *ret_panel)
  88. {
  89. esp_err_t ret = ESP_OK;
  90. gc9309na_panel_t *gc9309 = NULL;
  91. ESP_GOTO_ON_FALSE(io && panel_dev_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid arg");
  92. gc9309 = calloc(1, sizeof(gc9309na_panel_t));
  93. ESP_GOTO_ON_FALSE(gc9309, ESP_ERR_NO_MEM, err, TAG, "no mem");
  94. // Hardware reset GPIO config
  95. if (panel_dev_config->reset_gpio_num >= 0) {
  96. gpio_config_t io_conf = {
  97. .mode = GPIO_MODE_OUTPUT,
  98. .pin_bit_mask = 1ULL << panel_dev_config->reset_gpio_num,
  99. };
  100. ESP_GOTO_ON_ERROR(gpio_config(&io_conf), err, TAG, "GPIO config failed");
  101. }
  102. gc9309->colmod_val = 0x55; // RGB565
  103. // Initial register values
  104. gc9309->fb_bits_per_pixel = 16;
  105. gc9309->io = io;
  106. gc9309->reset_gpio_num = panel_dev_config->reset_gpio_num;
  107. gc9309->reset_level = panel_dev_config->flags.reset_active_high;
  108. gc9309->x_gap = 0;
  109. gc9309->y_gap = 0;
  110. // Function pointers
  111. gc9309->base.del = panel_gc9309na_del;
  112. gc9309->base.reset = panel_gc9309na_reset;
  113. gc9309->base.init = panel_gc9309na_init;
  114. gc9309->base.draw_bitmap = panel_gc9309na_draw_bitmap;
  115. gc9309->base.invert_color = panel_gc9309na_invert_color;
  116. gc9309->base.set_gap = panel_gc9309na_set_gap;
  117. gc9309->base.mirror = panel_gc9309na_mirror;
  118. gc9309->base.swap_xy = panel_gc9309na_swap_xy;
  119. gc9309->base.disp_on_off = panel_gc9309na_disp_on_off;
  120. gc9309->base.disp_sleep = panel_gc9309na_sleep;
  121. *ret_panel = &(gc9309->base);
  122. ESP_LOGI(TAG, "New GC9309NA panel @%p", gc9309);
  123. return ESP_OK;
  124. err:
  125. if (gc9309) {
  126. if (panel_dev_config->reset_gpio_num >= 0) {
  127. gpio_reset_pin(panel_dev_config->reset_gpio_num);
  128. }
  129. free(gc9309);
  130. }
  131. return ret;
  132. }
  133. static esp_err_t panel_gc9309na_del(esp_lcd_panel_t *panel)
  134. {
  135. gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  136. if (gc9309->reset_gpio_num >= 0) {
  137. gpio_reset_pin(gc9309->reset_gpio_num);
  138. }
  139. free(gc9309);
  140. ESP_LOGI(TAG, "Del GC9309NA panel");
  141. return ESP_OK;
  142. }
  143. static esp_err_t panel_gc9309na_reset(esp_lcd_panel_t *panel)
  144. {
  145. gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  146. if (gc9309->reset_gpio_num >= 0) {
  147. // Hardware reset
  148. gpio_set_level(gc9309->reset_gpio_num, gc9309->reset_level);
  149. vTaskDelay(pdMS_TO_TICKS(10));
  150. gpio_set_level(gc9309->reset_gpio_num, !gc9309->reset_level);
  151. vTaskDelay(pdMS_TO_TICKS(120));
  152. } else {
  153. // Software reset
  154. // uint8_t unlock_cmd[] = {GC9309NA_CMD_REG_ENABLE1, GC9309NA_CMD_REG_ENABLE2};
  155. // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(gc9309->io, 0xFE, unlock_cmd, 2),
  156. // TAG, "Unlock failed");
  157. // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(gc9309->io, LCD_CMD_SWRESET, NULL, 0),
  158. // TAG, "SW Reset failed");
  159. vTaskDelay(pdMS_TO_TICKS(120));
  160. }
  161. return ESP_OK;
  162. }
  163. static esp_err_t panel_gc9309na_init(esp_lcd_panel_t *panel)
  164. {
  165. gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  166. esp_lcd_panel_io_handle_t io = gc9309->io;
  167. // Unlock commands
  168. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xFE, NULL, 0), TAG, "Unlock cmd1 failed");
  169. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xEF, NULL, 0), TAG, "Unlock cmd2 failed");
  170. // Sleep out command
  171. //ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x11, NULL, 0), TAG, "Sleep out failed");
  172. //vTaskDelay(pdMS_TO_TICKS(80));
  173. // Timing control commands
  174. //ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xE8, (uint8_t[]){0xA0}, 1), TAG, "Timing control failed");
  175. //ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xE8, (uint8_t[]){0xF0}, 1), TAG, "Timing control failed");
  176. // Display on command
  177. //ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x29, NULL, 0), TAG, "Display on failed");
  178. // vTaskDelay(pdMS_TO_TICKS(10));
  179. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x80, (uint8_t[]){0xC0}, 1), TAG, "DINV failed");
  180. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x81, (uint8_t[]){0x01}, 1), TAG, "DINV failed");
  181. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x82, (uint8_t[]){0x07}, 1), TAG, "DINV failed");
  182. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x83, (uint8_t[]){0x38}, 1), TAG, "DINV failed");
  183. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x88, (uint8_t[]){0x64}, 1), TAG, "DINV failed");
  184. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x89, (uint8_t[]){0x86}, 1), TAG, "DINV failed");
  185. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x8B, (uint8_t[]){0x3C}, 1), TAG, "DINV failed");
  186. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x8D, (uint8_t[]){0x51}, 1), TAG, "DINV failed");
  187. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x8E, (uint8_t[]){0x70}, 1), TAG, "DINV failed");
  188. //高低位交换
  189. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xB4, (uint8_t[]){0x80}, 1), TAG, "DINV failed");
  190. gc9309->colmod_val = 0x05; // RGB565
  191. gc9309->madctl_val = 0x48; // BGR顺序,设置bit3=1(即0x08)
  192. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9309NA_CMD_COLMOD, &gc9309->colmod_val, 1), TAG, "DINV failed");
  193. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, GC9309NA_CMD_MADCTL, &gc9309->madctl_val, 1), TAG, "DINV failed");
  194. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0XBF, (uint8_t[]){0X1F}, 1), TAG, "DINV failed");
  195. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x7d, (uint8_t[]){0x45,0x06}, 2), TAG, "DINV failed");
  196. // Continue from where you left off
  197. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xEE, (uint8_t[]){0x00,0x06}, 2), TAG, "DINV failed");
  198. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0XF4, (uint8_t[]){0x53}, 1), TAG, "DINV failed");
  199. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xF6, (uint8_t[]){0x17,0x08}, 2), TAG, "DINV failed");
  200. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x70, (uint8_t[]){0x4F,0x4F}, 2), TAG, "DINV failed");
  201. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x71, (uint8_t[]){0x12,0x20}, 2), TAG, "DINV failed");
  202. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x72, (uint8_t[]){0x12,0x20}, 2), TAG, "DINV failed");
  203. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xB5, (uint8_t[]){0x50}, 1), TAG, "DINV failed");
  204. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xBA, (uint8_t[]){0x00}, 1), TAG, "DINV failed");
  205. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xEC, (uint8_t[]){0x71}, 1), TAG, "DINV failed");
  206. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x7b, (uint8_t[]){0x00,0x0d}, 2), TAG, "DINV failed");
  207. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x7c, (uint8_t[]){0x0d,0x03}, 2), TAG, "DINV failed");
  208. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0XF5, (uint8_t[]){0x02,0x10,0x12}, 3), TAG, "DINV failed");
  209. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xF0, (uint8_t[]){0x0C,0x11,0x0b,0x0a,0x05,0x32,0x44,0x8e,0x9a,0x29,0x2E,0x5f}, 12), TAG, "DINV failed");
  210. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xF1, (uint8_t[]){0x0B,0x11,0x0b,0x07,0x07,0x32,0x45,0xBd,0x8D,0x21,0x28,0xAf}, 12), TAG, "DINV failed");
  211. // 240x296 resolution settings
  212. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x2a, (uint8_t[]){0x00,0x00,0x00,0xef}, 4), TAG, "DINV failed");
  213. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x2b, (uint8_t[]){0x00,0x00,0x01,0x27}, 4), TAG, "DINV failed");
  214. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x66, (uint8_t[]){0x2C}, 1), TAG, "DINV failed");
  215. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x67, (uint8_t[]){0x18}, 1), TAG, "DINV failed");
  216. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x68, (uint8_t[]){0x3E}, 1), TAG, "DINV failed");
  217. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xCA, (uint8_t[]){0x0E}, 1), TAG, "DINV failed");
  218. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xe8, (uint8_t[]){0xf0}, 1), TAG, "DINV failed");
  219. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xCB, (uint8_t[]){0x06}, 1), TAG, "DINV failed");
  220. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xB6, (uint8_t[]){0x5C,0x40,0x40}, 3), TAG, "DINV failed");
  221. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xCC, (uint8_t[]){0x33}, 1), TAG, "DINV failed");
  222. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xCD, (uint8_t[]){0x33}, 1), TAG, "DINV failed");
  223. // Sleep out command
  224. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x11, NULL, 0), TAG, "Sleep out failed");
  225. vTaskDelay(pdMS_TO_TICKS(80));
  226. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xe8, (uint8_t[]){0xA0}, 1), TAG, "DINV failed");
  227. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xe8, (uint8_t[]){0xf0}, 1), TAG, "DINV failed");
  228. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xfe, NULL, 0), TAG, "unlock cmd1 failed");
  229. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0xee, NULL, 0), TAG, "unlock cmd2 failed");
  230. // Display on command
  231. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x29, NULL, 0), TAG, "Display on failed");
  232. // Memory write command
  233. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, 0x2c, NULL, 0), TAG, "Memory write failed");
  234. vTaskDelay(pdMS_TO_TICKS(10));
  235. return ESP_OK;
  236. }
  237. static esp_err_t panel_gc9309na_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
  238. {
  239. gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  240. esp_lcd_panel_io_handle_t io = gc9309->io;
  241. x_start += gc9309->x_gap;
  242. x_end += gc9309->x_gap;
  243. y_start += gc9309->y_gap;
  244. y_end += gc9309->y_gap;
  245. // define an area of frame memory where MCU can access
  246. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_CASET, (uint8_t[]) {
  247. (x_start >> 8) & 0xFF,
  248. x_start & 0xFF,
  249. ((x_end - 1) >> 8) & 0xFF,
  250. (x_end - 1) & 0xFF,
  251. }, 4), TAG, "io tx param failed");
  252. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_RASET, (uint8_t[]) {
  253. (y_start >> 8) & 0xFF,
  254. y_start & 0xFF,
  255. ((y_end - 1) >> 8) & 0xFF,
  256. (y_end - 1) & 0xFF,
  257. }, 4), TAG, "io tx param failed");
  258. // transfer frame buffer
  259. size_t len = (x_end - x_start) * (y_end - y_start) * gc9309->fb_bits_per_pixel / 8;
  260. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_color(io, LCD_CMD_RAMWR, color_data, len), TAG, "io tx color failed");
  261. return ESP_OK;
  262. }
  263. static esp_err_t panel_gc9309na_invert_color(esp_lcd_panel_t *panel, bool invert_color_data)
  264. {
  265. gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  266. esp_lcd_panel_io_handle_t io = gc9309->io;
  267. int command = 0;
  268. if (invert_color_data) {
  269. command = LCD_CMD_INVON;
  270. } else {
  271. command = LCD_CMD_INVOFF;
  272. }
  273. ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, command, NULL, 0), TAG,
  274. "io tx param failed");
  275. return ESP_OK;
  276. }
  277. static esp_err_t panel_gc9309na_mirror(esp_lcd_panel_t *panel, bool mirror_x, bool mirror_y)
  278. {
  279. // gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  280. // esp_lcd_panel_io_handle_t io = gc9309->io;
  281. // if (mirror_x) {
  282. // gc9309->madctl_val |= LCD_CMD_MX_BIT;
  283. // } else {
  284. // gc9309->madctl_val &= ~LCD_CMD_MX_BIT;
  285. // }
  286. // if (mirror_y) {
  287. // gc9309->madctl_val |= LCD_CMD_MY_BIT;
  288. // } else {
  289. // gc9309->madctl_val &= ~LCD_CMD_MY_BIT;
  290. // }
  291. // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
  292. // gc9309->madctl_val
  293. // }, 1), TAG, "io tx param failed");
  294. return ESP_OK;
  295. }
  296. static esp_err_t panel_gc9309na_swap_xy(esp_lcd_panel_t *panel, bool swap_axes)
  297. {
  298. // gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  299. // esp_lcd_panel_io_handle_t io = gc9309->io;
  300. // if (swap_axes) {
  301. // gc9309->madctl_val |= LCD_CMD_MV_BIT;
  302. // } else {
  303. // gc9309->madctl_val &= ~LCD_CMD_MV_BIT;
  304. // }
  305. // ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(io, LCD_CMD_MADCTL, (uint8_t[]) {
  306. // gc9309->madctl_val
  307. // }, 1), TAG, "io tx param failed");
  308. return ESP_OK;
  309. }
  310. static esp_err_t panel_gc9309na_set_gap(esp_lcd_panel_t *panel, int x_gap, int y_gap)
  311. {
  312. gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  313. gc9309->x_gap = x_gap;
  314. gc9309->y_gap = y_gap;
  315. return ESP_OK;
  316. }
  317. static esp_err_t panel_gc9309na_disp_on_off(esp_lcd_panel_t *panel, bool on_off)
  318. {
  319. gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  320. uint8_t cmd = on_off ? GC9309NA_CMD_DISPON : GC9309NA_CMD_DISPOFF;
  321. return esp_lcd_panel_io_tx_param(gc9309->io, cmd, NULL, 0);
  322. }
  323. static esp_err_t panel_gc9309na_sleep(esp_lcd_panel_t *panel, bool sleep)
  324. {
  325. gc9309na_panel_t *gc9309 = __containerof(panel, gc9309na_panel_t, base);
  326. uint8_t cmd = sleep ? GC9309NA_CMD_SLPIN : GC9309NA_CMD_SLPOUT;
  327. esp_err_t ret = esp_lcd_panel_io_tx_param(gc9309->io, cmd, NULL, 0);
  328. vTaskDelay(pdMS_TO_TICKS(120));
  329. return ret;
  330. }