Skip to content

Conversation

@finger563
Copy link
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.
…ers to allow decode failures to be discarded without visual artifacts
@github-actions
Copy link

✅Static analysis result - no issues found! ✅

@finger563 finger563 requested a review from Copilot August 16, 2025 04:36
Copy link

Copilot AI left a comment

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 adds support for the Waveshare S3 Touch hardware platform and implements a framebuffer-based video rendering system to improve robustness against JPEG decode failures. The implementation separates JPEG decoding from display operations to prevent visual artifacts when decode errors occur.

Key changes:

  • Added Waveshare S3 Touch hardware configuration and dependencies
  • Implemented dual framebuffer system with separate decode and display buffers
  • Refactored video rendering into a dedicated task with queue-based frame processing

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
main/main.cpp Core implementation with framebuffer allocation, video task, and updated JPEG decode/display pipeline
main/idf_component.yml Added ws-s3-touch component dependency
main/Kconfig.projbuild Added Waveshare S3 Touch hardware configuration option
CMakeLists.txt Updated component list to include ws-s3-touch

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

return true; // we're done with our work, no need to run again, so stop the task
}

static size_t frame_buffer_index = 0;
Copy link

Copilot AI Aug 16, 2025

Choose a reason for hiding this comment

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

The static variable frame_buffer_index is accessed from multiple tasks (display task and video task) without synchronization. This creates a race condition that could lead to corruption or incorrect buffer selection. Consider using atomic operations or protecting access with a mutex.

Suggested change
static size_t frame_buffer_index = 0;
static size_t frame_buffer_index = 0;
static std::mutex frame_buffer_index_mutex;
Copilot uses AI. Check for mistakes.
xQueueSend(video_queue_, &buffer, portMAX_DELAY);
}

void IRAM_ATTR push_frame(const void *frame) { xQueueSend(video_queue_, &frame, portMAX_DELAY); }
Copy link

Copilot AI Aug 16, 2025

Choose a reason for hiding this comment

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

The function passes the address of the local parameter frame to the queue instead of the frame pointer value itself. This should be xQueueSend(video_queue_, &frame, portMAX_DELAY) where frame is already a pointer, or the queue should be defined to hold void* directly rather than uint16_t*.

Copilot uses AI. Check for mistakes.
uint32_t *src = (uint32_t *)&_frame[(y + i) * lcd_width + j];
uint32_t *dst = (uint32_t *)&_buf[i * lcd_width + j];
dst[0] = src[0]; // copy two pixels (32 bits) at a time
}
Copy link

Copilot AI Aug 16, 2025

Choose a reason for hiding this comment

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

The loop assumes lcd_width is always even, but if it's odd, this will access memory beyond the allocated buffer bounds on the last iteration. Add a check to handle odd widths or ensure the loop doesn't exceed the buffer size.

Suggested change
}
int j = 0;
for (; j + 1 < lcd_width; j += 2) {
uint32_t *src = (uint32_t *)&_frame[(y + i) * lcd_width + j];
uint32_t *dst = (uint32_t *)&_buf[i * lcd_width + j];
dst[0] = src[0]; // copy two pixels (32 bits) at a time
}
// If lcd_width is odd, copy the last pixel
if (lcd_width % 2 != 0) {
_buf[i * lcd_width + lcd_width - 1] = _frame[(y + i) * lcd_width + lcd_width - 1];
}
Copilot uses AI. Check for mistakes.
return true;
}

video_queue_ = xQueueCreate(1, sizeof(uint16_t *));
Copy link

Copilot AI Aug 16, 2025

Choose a reason for hiding this comment

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

The queue is created to hold uint16_t* but the push_frame function expects to store void*. This type mismatch could cause issues on platforms where pointer sizes differ. The queue should be created with sizeof(void*) to match the actual usage.

Suggested change
video_queue_ = xQueueCreate(1, sizeof(uint16_t *));
video_queue_ = xQueueCreate(1, sizeof(void *));
Copilot uses AI. Check for mistakes.
// special case: if _frame_ptr is null, then we simply fill the screen with 0
if (_frame_ptr == nullptr) {
for (int y = 0; y < lcd_height; y += num_lines_to_write) {
Pixel *_buf = (Pixel *)((uint32_t)vram0 * (vram_index ^ 0x01) + (uint32_t)vram1 * vram_index);
Copy link

Copilot AI Aug 16, 2025

Choose a reason for hiding this comment

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

The buffer selection logic (uint32_t)vram0 * (vram_index ^ 0x01) + (uint32_t)vram1 * vram_index is duplicated and complex. Extract this into a helper function or use a simpler ternary operator like vram_index ? vram1 : vram0 for better readability and maintainability.

Suggested change
Pixel *_buf = (Pixel *)((uint32_t)vram0 * (vram_index ^ 0x01) + (uint32_t)vram1 * vram_index);
Pixel *_buf = (Pixel *)(vram_index ? vram1 : vram0);
Copilot uses AI. Check for mistakes.
@finger563 finger563 merged commit b9077ab into main Aug 16, 2025
2 checks passed
@finger563 finger563 deleted the feat/display-improvements branch August 16, 2025 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants