Skip to content

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
mainfrom
feat/tab5-fast-rotation
Open

feat(m5stack-tab5): Update tab5 video and example to have larger display buffers and use the PPU for faster refresh and display rotation#675
finger563 wants to merge 2 commits into
mainfrom
feat/tab5-fast-rotation

Conversation

@finger563

Copy link
Copy Markdown
Contributor

Description

Motivation and Context

How has this been tested?

Screenshots (if appropriate, e.g. schematic, board, console logs, lab pictures):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation Update
  • Hardware (schematic, board, system design) change
  • Software change

Checklist:

  • My change requires a change to the documentation.
  • I have added / updated the documentation related to this change via either README or WIKI

Software

  • I have added tests to cover my changes.
  • I have updated the .github/workflows/build.yml file to add my new test to the automated cloud build github action.
  • All new and existing tests passed.
  • My code follows the code style of this project.

Hardware

  • I have updated the design files (schematic, board, libraries).
  • I have attached the PDFs of the SCH / BRD to this PR
  • I have updated the design output (GERBER, BOM) files.

…lay buffers and use the PPU for faster refresh and display rotation
Copilot AI review requested due to automatic review settings July 23, 2026 19:42
@github-actions

Copy link
Copy Markdown

✅Static analysis result - no issues found! ✅

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 thread components/m5stack-tab5/src/video.cpp
Comment thread components/m5stack-tab5/src/video.cpp
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>
Copilot AI review requested due to automatic review settings July 23, 2026 20:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants