diff --git a/components/esp_lcd/include/esp_lcd_panel_rgb.h b/components/esp_lcd/include/esp_lcd_panel_rgb.h index 082ce45f96..6ef51de9db 100644 --- a/components/esp_lcd/include/esp_lcd_panel_rgb.h +++ b/components/esp_lcd/include/esp_lcd_panel_rgb.h @@ -99,14 +99,25 @@ typedef bool (*esp_lcd_rgb_panel_vsync_cb_t)(esp_lcd_panel_handle_t panel, const */ typedef bool (*esp_lcd_rgb_panel_bounce_buf_fill_cb_t)(esp_lcd_panel_handle_t panel, void *bounce_buf, int pos_px, int len_bytes, void *user_ctx); +/** + * @brief Prototype for the function to be called when the bounce buffer finish copying the entire frame. + * + * @param[in] panel LCD panel handle, returned from `esp_lcd_new_rgb_panel` + * @param[in] edata Panel event data, fed by driver + * @param[in] user_ctx User data, passed from `esp_lcd_rgb_panel_register_event_callbacks()` + * @return Whether a high priority task has been waken up by this function + */ +typedef bool (*esp_lcd_rgb_panel_bounce_buf_finish_cb_t)(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx); + /** * @brief Group of supported RGB LCD panel callbacks * @note The callbacks are all running under ISR environment * @note When CONFIG_LCD_RGB_ISR_IRAM_SAFE is enabled, the callback itself and functions called by it should be placed in IRAM. */ typedef struct { - esp_lcd_rgb_panel_vsync_cb_t on_vsync; /*!< VSYNC event callback */ - esp_lcd_rgb_panel_bounce_buf_fill_cb_t on_bounce_empty; /*!< Bounce buffer empty callback. */ + esp_lcd_rgb_panel_vsync_cb_t on_vsync; /*!< VSYNC event callback */ + esp_lcd_rgb_panel_bounce_buf_fill_cb_t on_bounce_empty; /*!< Bounce buffer empty callback. */ + esp_lcd_rgb_panel_bounce_buf_finish_cb_t on_bounce_frame_finish; /*!< Bounce buffer finish callback. */ } esp_lcd_rgb_panel_event_callbacks_t; /** diff --git a/components/esp_lcd/src/esp_lcd_panel_rgb.c b/components/esp_lcd/src/esp_lcd_panel_rgb.c index 505cfb9b5c..dc1c2e1a3f 100644 --- a/components/esp_lcd/src/esp_lcd_panel_rgb.c +++ b/components/esp_lcd/src/esp_lcd_panel_rgb.c @@ -109,6 +109,7 @@ struct esp_rgb_panel_t { gdma_channel_handle_t dma_chan; // DMA channel handle esp_lcd_rgb_panel_vsync_cb_t on_vsync; // VSYNC event callback esp_lcd_rgb_panel_bounce_buf_fill_cb_t on_bounce_empty; // callback used to fill a bounce buffer rather than copying from the frame buffer + esp_lcd_rgb_panel_bounce_buf_finish_cb_t on_bounce_frame_finish; // callback used to notify when the bounce buffer finish copying the entire frame void *user_ctx; // Reserved user's data of callback functions int x_gap; // Extra gap in x coordinate, it's used when calculate the flush window int y_gap; // Extra gap in y coordinate, it's used when calculate the flush window @@ -360,12 +361,16 @@ esp_err_t esp_lcd_rgb_panel_register_event_callbacks(esp_lcd_panel_handle_t pane if (callbacks->on_bounce_empty) { ESP_RETURN_ON_FALSE(esp_ptr_in_iram(callbacks->on_bounce_empty), ESP_ERR_INVALID_ARG, TAG, "on_bounce_empty callback not in IRAM"); } + if (callbacks->on_bounce_frame_finish) { + ESP_RETURN_ON_FALSE(esp_ptr_in_iram(callbacks->on_bounce_frame_finish), ESP_ERR_INVALID_ARG, TAG, "on_bounce_frame_finish callback not in IRAM"); + } if (user_ctx) { ESP_RETURN_ON_FALSE(esp_ptr_internal(user_ctx), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM"); } #endif // CONFIG_LCD_RGB_ISR_IRAM_SAFE rgb_panel->on_vsync = callbacks->on_vsync; rgb_panel->on_bounce_empty = callbacks->on_bounce_empty; + rgb_panel->on_bounce_frame_finish = callbacks->on_bounce_frame_finish; rgb_panel->user_ctx = user_ctx; return ESP_OK; } @@ -889,7 +894,9 @@ static IRAM_ATTR bool lcd_rgb_panel_fill_bounce_buffer(esp_rgb_panel_t *panel, u if (panel->num_fbs == 0) { if (panel->on_bounce_empty) { // We don't have a frame buffer here; we need to call a callback to refill the bounce buffer - need_yield = panel->on_bounce_empty(&panel->base, buffer, panel->bounce_pos_px, panel->bb_size, panel->user_ctx); + if (panel->on_bounce_empty(&panel->base, buffer, panel->bounce_pos_px, panel->bb_size, panel->user_ctx)) { + need_yield = true; + } } } else { // We do have frame buffer; copy from there. @@ -910,6 +917,11 @@ static IRAM_ATTR bool lcd_rgb_panel_fill_bounce_buffer(esp_rgb_panel_t *panel, u if (panel->bounce_pos_px >= panel->fb_size / bytes_per_pixel) { panel->bounce_pos_px = 0; panel->bb_fb_index = panel->cur_fb_index; + if (panel->on_bounce_frame_finish) { + if (panel->on_bounce_frame_finish(&panel->base, NULL, panel->user_ctx)) { + need_yield = true; + } + } } if (panel->num_fbs > 0) { // Preload the next bit of buffer from psram