88
99constexpr const char * TAG = " AXS15231B" ;
1010
11+ typedef struct
12+ {
13+ SemaphoreHandle_t te_v_sync_sem;
14+ SemaphoreHandle_t te_catch_sem;
15+ uint32_t time_Tvdl;
16+ uint32_t time_Tvdh;
17+ uint32_t te_timestamp;
18+ portMUX_TYPE lock;
19+ } lcd_tear_t ;
20+
21+ lcd_tear_t *tear_ctx = nullptr ;
22+
1123static const axs15231b_lcd_init_cmd_t lcd_init_cmds[] = {
1224 {0xBB , (uint8_t []){0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x5A , 0xA5 }, 8 , 0 },
1325 {0xA0 , (uint8_t []){0xC0 , 0x10 , 0x00 , 0x02 , 0x00 , 0x00 , 0x04 , 0x3F , 0x20 , 0x05 , 0x3F , 0x3F , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 }, 17 , 0 },
@@ -43,6 +55,58 @@ static const axs15231b_lcd_init_cmd_t lcd_init_cmds[] = {
4355 {0x2C , (uint8_t []){0x00 , 0x00 , 0x00 , 0x00 }, 4 , 0 }
4456};
4557
58+ static void display_sync_cb (lv_event_t *e)
59+ {
60+ lcd_tear_t *tear_handle = (lcd_tear_t *)lv_event_get_user_data (e);
61+
62+ if (tear_handle == nullptr || tear_handle->te_v_sync_sem == nullptr )
63+ {
64+ return ;
65+ }
66+
67+ if (tear_handle->te_catch_sem )
68+ {
69+ xSemaphoreGive (tear_handle->te_catch_sem );
70+ }
71+
72+ xSemaphoreTake (tear_handle->te_v_sync_sem , pdMS_TO_TICKS (100 ));
73+ }
74+
75+ static void display_sync_task (void *arg)
76+ {
77+ assert (arg);
78+ lcd_tear_t *tear_handle = (lcd_tear_t *)arg;
79+
80+ while (true )
81+ {
82+ if (pdPASS != xSemaphoreTake (tear_handle->te_catch_sem , pdMS_TO_TICKS (tear_handle->time_Tvdl )))
83+ {
84+ xSemaphoreTake (tear_handle->te_v_sync_sem , 0 );
85+ }
86+ }
87+ vTaskDelete (nullptr );
88+ }
89+
90+ static void IRAM_ATTR display_tear_interrupt (void *arg)
91+ {
92+ assert (arg);
93+ lcd_tear_t *tear_handle = (lcd_tear_t *)arg;
94+ BaseType_t xHigherPriorityTaskAwoken = pdFALSE;
95+
96+ if (tear_handle->te_v_sync_sem )
97+ {
98+ portENTER_CRITICAL_ISR (&tear_handle->lock );
99+ tear_handle->te_timestamp = esp_log_timestamp ();
100+ portEXIT_CRITICAL_ISR (&tear_handle->lock );
101+ xSemaphoreGiveFromISR (tear_handle->te_v_sync_sem , &xHigherPriorityTaskAwoken);
102+
103+ if (xHigherPriorityTaskAwoken)
104+ {
105+ portYIELD_FROM_ISR ();
106+ }
107+ }
108+ }
109+
46110bool Axs15231bDisplay::createIoHandle (esp_lcd_panel_io_handle_t & outHandle) {
47111 const esp_lcd_panel_io_spi_config_t panel_io_config = {
48112 .cs_gpio_num = configuration->csPin ,
@@ -72,6 +136,9 @@ bool Axs15231bDisplay::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
72136}
73137
74138bool Axs15231bDisplay::createPanelHandle (esp_lcd_panel_io_handle_t ioHandle, esp_lcd_panel_handle_t & panelHandle) {
139+ SemaphoreHandle_t te_catch_sem = nullptr ;
140+ SemaphoreHandle_t te_v_sync_sem = nullptr ;
141+
75142 const axs15231b_vendor_config_t vendor_config = {
76143 .init_cmds = lcd_init_cmds,
77144 .init_cmds_size = sizeof (lcd_init_cmds) / sizeof (lcd_init_cmds[0 ]),
@@ -127,6 +194,45 @@ bool Axs15231bDisplay::createPanelHandle(esp_lcd_panel_io_handle_t ioHandle, esp
127194 return false ;
128195 }
129196
197+ // TE sync initialization
198+ uint32_t time_Tvdl = 13 ;
199+ uint32_t time_Tvdh = 3 ;
200+
201+ if (configuration->te_gpio_num > 0 )
202+ {
203+ tear_ctx = malloc (sizeof (lcd_tear_t ));
204+ // ESP_GOTO_ON_FALSE(tear_ctx != NULL, ESP_ERR_NO_MEM, err, TAG, "Not enough memory for tear_ctx allocation!");
205+
206+ te_v_sync_sem = xSemaphoreCreateCounting (1 , 0 );
207+ // ESP_GOTO_ON_FALSE(te_v_sync_sem, ESP_ERR_NO_MEM, err, TAG, "Not enough memory for te_v_sync_sem Semaphore.");
208+ tear_ctx->te_v_sync_sem = te_v_sync_sem;
209+
210+ te_catch_sem = xSemaphoreCreateCounting (1 , 0 );
211+ // ESP_GOTO_ON_FALSE(te_catch_sem, ESP_ERR_NO_MEM, err, TAG, "Not enough memory for te_catch_sem Semaphore.");
212+ tear_ctx->te_catch_sem = te_catch_sem;
213+
214+ tear_ctx->time_Tvdl = time_Tvdl;
215+ tear_ctx->time_Tvdh = time_Tvdh;
216+ tear_ctx->lock .owner = portMUX_FREE_VAL;
217+ tear_ctx->lock .count = 0 ;
218+
219+ const gpio_config_t te_detect_cfg = {
220+ .intr_type = GPIO_INTR_NEGEDGE,
221+ .mode = GPIO_MODE_INPUT,
222+ .pin_bit_mask = BIT64 (configuration->te_gpio_num ),
223+ .pull_down_en = GPIO_PULLDOWN_DISABLE,
224+ .pull_up_en = GPIO_PULLUP_ENABLE};
225+
226+ ESP_ERROR_CHECK (gpio_config (&te_detect_cfg));
227+ gpio_install_isr_service (0 );
228+ ESP_ERROR_CHECK (gpio_isr_handler_add (configuration->te_gpio_num , display_tear_interrupt, tear_ctx));
229+
230+ BaseType_t res = xTaskCreate (display_sync_task, " Tear Task" , 2048 , tear_ctx, 4 , NULL );
231+ // ESP_GOTO_ON_FALSE(res == pdPASS, ESP_FAIL, err, TAG, "Create Sync Task Fail!");
232+ }
233+
234+ lv_display_add_event_cb (lvgl_disp, display_sync_cb, LV_EVENT_FLUSH_START, tear_ctx);
235+
130236 return true ;
131237}
132238
@@ -137,7 +243,7 @@ lvgl_port_display_cfg_t Axs15231bDisplay::getLvglPortDisplayConfig(esp_lcd_panel
137243 .control_handle = nullptr ,
138244 .buffer_size = configuration->bufferSize ,
139245 .double_buffer = true ,
140- .trans_size = 0 ,
246+ .trans_size = configuration-> horizontalResolution * configuration-> verticalResolution / 4 ,
141247 .hres = configuration->horizontalResolution ,
142248 .vres = configuration->verticalResolution ,
143249 .monochrome = false ,
@@ -148,7 +254,7 @@ lvgl_port_display_cfg_t Axs15231bDisplay::getLvglPortDisplayConfig(esp_lcd_panel
148254 },
149255 .color_format = LV_COLOR_FORMAT_RGB565,
150256 .flags = {
151- .buff_dma = true ,
257+ .buff_dma = false ,
152258 .buff_spiram = true ,
153259 .sw_rotate = true ,
154260 .swap_bytes = true ,
0 commit comments