feat(m5stack-tab5): Update tab5 video and example to have larger display buffers and use the PPU for faster refresh and display rotation#675
Open
finger563 wants to merge 2 commits into
Open
Conversation
…lay buffers and use the PPU for faster refresh and display rotation
|
✅Static analysis result - no issues found! ✅ |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the M5Stack Tab5 display/video path to improve refresh performance and enable faster display rotation by moving LVGL draw buffers into PSRAM and using the ESP32-P4 PPA (Pixel Processing Accelerator) for hardware rotation.
Changes:
- Allocate LVGL draw buffers in PSRAM and add a PSRAM-aligned scratch buffer for rotation output.
- Add PPA-based hardware rotation in the LVGL flush path with a software-rotation fallback.
- Update the Tab5 example to use a full-frame LVGL pixel buffer for single-pass full-screen flushes.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| components/m5stack-tab5/src/video.cpp | Moves draw buffers to PSRAM, adds PPA client + aligned rotation scratch buffer, and performs rotation in flush() via PPA with SW fallback. |
| components/m5stack-tab5/example/main/m5stack_tab5_example.cpp | Switches the example to a full-frame LVGL pixel buffer to avoid progressive “striped” redraws on full-screen updates. |
| components/m5stack-tab5/CMakeLists.txt | Adds esp_driver_ppa dependency required for PPA rotation. |
Comment on lines
+458
to
+461
| srm.scale_x = 1.0f; | ||
| srm.scale_y = 1.0f; | ||
| srm.mode = PPA_TRANS_MODE_BLOCKING; | ||
| ppa_do_scale_rotate_mirror(g_ppa_client, &srm); |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
components/m5stack-tab5/src/video.cpp:449
- The comment says the PPA rotation direction is counter-clockwise vs LVGL’s clockwise rotation (LVGL 90 -> PPA 270 and LVGL 270 -> PPA 90), but the current mapping uses the same angles (90->90, 270->270). This mismatch will either rotate the image the wrong way or leave misleading documentation; align the mapping with the documented behavior.
// Hardware rotation via the PPA. NOTE: the PPA rotates COUNTER-clockwise
// while LVGL's rotation is clockwise, so LVGL 90 -> PPA 270 and LVGL 270
// -> PPA 90 (180 is the same). If the rotated image comes out turned the
// wrong way, swap the 90/270 mapping here. For 90/270 the output picture
// width/height are swapped.
ppa_srm_rotation_angle_t angle = PPA_SRM_ROTATION_ANGLE_0;
uint32_t out_w = ww, out_h = hh;
if (rotation == LV_DISPLAY_ROTATION_90) {
angle = PPA_SRM_ROTATION_ANGLE_90;
out_w = hh;
out_h = ww;
} else if (rotation == LV_DISPLAY_ROTATION_180) {
angle = PPA_SRM_ROTATION_ANGLE_180;
} else if (rotation == LV_DISPLAY_ROTATION_270) {
angle = PPA_SRM_ROTATION_ANGLE_270;
Comment on lines
+340
to
+343
| if (third_buffer == nullptr) { | ||
| logger_.error("Could not allocate the rotation scratch buffer ({} bytes)", third_buffer_bytes); | ||
| third_buffer_bytes = 0; | ||
| } |
Comment on lines
415
to
+469
| void IRAM_ATTR M5StackTab5::flush(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) { | ||
| // Note: This function may be called from ISR context via DPI callback | ||
| // Avoid using floating-point operations, logging, or other coprocessor functions | ||
|
|
||
| if (lcd_handles_.panel == nullptr) { | ||
| lv_display_flush_ready(disp); | ||
| return; | ||
| } | ||
|
|
||
| int offsetx1 = area->x1; | ||
| int offsetx2 = area->x2; | ||
| int offsety1 = area->y1; | ||
| int offsety2 = area->y2; | ||
|
|
||
| auto rotation = lv_display_get_rotation(lv_display_get_default()); | ||
| if (rotation > LV_DISPLAY_ROTATION_0) { | ||
| /* SW rotation */ | ||
| if (rotation > LV_DISPLAY_ROTATION_0 && third_buffer != nullptr) { | ||
| int32_t ww = lv_area_get_width(area); | ||
| int32_t hh = lv_area_get_height(area); | ||
| lv_color_format_t cf = lv_display_get_color_format(disp); | ||
| uint32_t w_stride = lv_draw_buf_width_to_stride(ww, cf); | ||
| uint32_t h_stride = lv_draw_buf_width_to_stride(hh, cf); | ||
| if (rotation == LV_DISPLAY_ROTATION_180) { | ||
| lv_draw_sw_rotate(px_map, third_buffer, hh, ww, h_stride, h_stride, LV_DISPLAY_ROTATION_180, | ||
| cf); | ||
| } else if (rotation == LV_DISPLAY_ROTATION_90) { | ||
| // printf("%ld %ld\n", w_stride, h_stride); | ||
| lv_draw_sw_rotate(px_map, third_buffer, ww, hh, w_stride, h_stride, LV_DISPLAY_ROTATION_90, | ||
| cf); | ||
| // // rotate_copy_pixel((uint16_t*)color_map, (uint16_t*)third_buffer, offsetx1, offsety1, | ||
| // // offsetx2, offsety2, LV_HOR_RES, LV_VER_RES, 270); | ||
| // rotate_copy_pixel((uint16_t*)color_map, (uint16_t*)third_buffer, 0, 0, offsetx2 - offsetx1, | ||
| // offsety2 - offsety1, offsetx2 - offsetx1 + 1, offsety2 - offsety1 + 1, | ||
| // 270); | ||
| } else if (rotation == LV_DISPLAY_ROTATION_270) { | ||
| lv_draw_sw_rotate(px_map, third_buffer, ww, hh, w_stride, h_stride, LV_DISPLAY_ROTATION_270, | ||
| cf); | ||
| if (g_ppa_client != nullptr) { | ||
| // Hardware rotation via the PPA. NOTE: the PPA rotates COUNTER-clockwise | ||
| // while LVGL's rotation is clockwise, so LVGL 90 -> PPA 270 and LVGL 270 | ||
| // -> PPA 90 (180 is the same). If the rotated image comes out turned the | ||
| // wrong way, swap the 90/270 mapping here. For 90/270 the output picture | ||
| // width/height are swapped. | ||
| ppa_srm_rotation_angle_t angle = PPA_SRM_ROTATION_ANGLE_0; | ||
| uint32_t out_w = ww, out_h = hh; | ||
| if (rotation == LV_DISPLAY_ROTATION_90) { | ||
| angle = PPA_SRM_ROTATION_ANGLE_90; | ||
| out_w = hh; | ||
| out_h = ww; | ||
| } else if (rotation == LV_DISPLAY_ROTATION_180) { | ||
| angle = PPA_SRM_ROTATION_ANGLE_180; | ||
| } else if (rotation == LV_DISPLAY_ROTATION_270) { | ||
| angle = PPA_SRM_ROTATION_ANGLE_270; | ||
| out_w = hh; | ||
| out_h = ww; | ||
| } | ||
| ppa_srm_oper_config_t srm = {}; | ||
| srm.in.buffer = px_map; | ||
| srm.in.pic_w = ww; | ||
| srm.in.pic_h = hh; | ||
| srm.in.block_w = ww; | ||
| srm.in.block_h = hh; | ||
| srm.in.srm_cm = PPA_SRM_COLOR_MODE_RGB565; | ||
| srm.out.buffer = third_buffer; | ||
| srm.out.buffer_size = third_buffer_bytes; | ||
| srm.out.pic_w = out_w; | ||
| srm.out.pic_h = out_h; | ||
| srm.out.srm_cm = PPA_SRM_COLOR_MODE_RGB565; | ||
| srm.rotation_angle = angle; | ||
| srm.scale_x = 1.0f; | ||
| srm.scale_y = 1.0f; | ||
| srm.mode = PPA_TRANS_MODE_BLOCKING; | ||
| ppa_do_scale_rotate_mirror(g_ppa_client, &srm); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Motivation and Context
How has this been tested?
Screenshots (if appropriate, e.g. schematic, board, console logs, lab pictures):
Types of changes
Checklist:
Software
.github/workflows/build.ymlfile to add my new test to the automated cloud build github action.Hardware