Skip to content

Conversation

@ppsx
Copy link

@ppsx ppsx commented Jan 30, 2026

Complete CircuitPython support for the Waveshare ESP32-S3 Touch AMOLED 2.41 board featuring:

  • Hardware-accelerated graphics (DMA, JPEG decoder)
  • Native Text - 7 built-in fonts (8×8 to 32×48)
  • Graphics - Lines, circles, rectangles, fills
  • Images - BMP and JPEG with hardware decoder
  • Double Buffering - Zero tearing animations
  • Performance - 60+ FPS capable

Documentation, technical details, examples, etc.:
https://github.com/ppsx/ws-esp32-s3-amoled-241

Copilot AI review requested due to automatic review settings January 30, 2026 17:58
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 pull request adds comprehensive CircuitPython support for the Waveshare ESP32-S3 Touch AMOLED 2.41 board, featuring a native RM690B0 AMOLED display driver with QSPI interface support, hardware-accelerated image conversion (BMP/JPEG), and ESP32-native SD card support.

Changes:

  • New rm690b0 module with native QSPI display driver supporting hardware DMA, built-in fonts (7 sizes), and drawing primitives
  • Image conversion utilities with BMP and JPEG support using hardware JPEG decoder where available, fallback to TJpgDec
  • espsdcard module providing ESP-IDF-based SD card interface compatible with sdcardio API

Reviewed changes

Copilot reviewed 32 out of 34 changed files in this pull request and generated 19 comments.

Show a summary per file
File Description
shared-bindings/rm690b0/*.{c,h} Python bindings for RM690B0 display driver and image conversion
ports/espressif/common-hal/rm690b0/*.{c,h} ESP32 implementation of RM690B0 driver with QSPI support
ports/espressif/common-hal/espsdcard/*.{c,h} ESP-IDF SD card driver implementation
ports/espressif/bindings/espsdcard/*.{c,h} Python bindings for SD card with dual API support
ports/espressif/boards/waveshare_esp32_s3_amoled_241/* Board definition files for Waveshare ESP32-S3 AMOLED 2.41
lib/esp_jpeg/* JPEG decoder wrapper using TJpgDec library
py/circuitpy_*.{mk,h} Build system configuration for new modules
ports/espressif/Makefile Build rules for rm690b0 and espsdcard modules
locale/circuitpython.pot Error message translations

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tannewt
Copy link
Member

tannewt commented Jan 30, 2026

Given the size and style of this PR I suspect it was done via LLM agent. In principle that is ok but I'd like you to say so upfront. Please also state 1) What prompts you did and 2) how you tested it.

@ppsx
Copy link
Author

ppsx commented Jan 30, 2026

Given the size and style of this PR I suspect it was done via LLM agent. In principle that is ok but I'd like you to say so upfront. Please also state 1) What prompts you did and 2) how you tested it.

This PR has been mostly created with AI agents usage. Claude Opus + Claude Sonnet + Gemini Pro. Can't tell exact prompts because there were thousands of them.
I was working on that port for over 4 months (with some breaks).

Testing - mostly manual. Hundreds of flashed builds. Tens of test scripts and performance benchmarks. Some of them I left in this repo: https://github.com/ppsx/ws-esp32-s3-amoled-241
You can find more info there if you're interested.
That was not a simple vibe-coding but really hard work with new tools helping in work.
Regarding the RM690B0 display driver - as far as I know that's the very first implementation of QSPI protocol for Circuitpython (and MicryPython).

If it doesn't fulfill your requirements - that's fine, I don't mind.
BTW, I've updated the code for all but one Copilot suggested "issues".

Copy link
Collaborator

@dhalbert dhalbert left a comment

Choose a reason for hiding this comment

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

There is a lot of of new device-specific code here, but underneath, there could be more generality that would add capabilities for more boards than this. It could be broken out into multiple PR's.

I am impressed by the amount of effort, but it has ended up being very specific.

  • espsdcard: instead of adding a new module, I think the implementation could have replaced sdcardio, with additional features that are not implemented on other ports.
  • JPEG support: can the ESP JPEG support replace the generic jpegio code?
  • fonts: why are the fonts compiled in just for this driver? What about existing font support? Could it be used? If not, how could existing generic font support be improved for what you want?
  • RM690B0 support: is this generalizable for other QSPI displays or other similar displays, or because it's wired for the ESP-provided driver, it's not?
  • Could the image_converter code be broken out into something more general?

@ppsx
Copy link
Author

ppsx commented Jan 30, 2026

Agree that I've added some code specifically for this board.

  • espsdcard - I've added that because I had a lot of issues with sdcardio module with this board. And, what's equally important, this native ESP module is more performant while reading/writing files (https://github.com/ppsx/ws-esp32-s3-amoled-241/blob/master/docs/TECHNICAL_NOTES.md#4-storage--io-considerations); I think it could be possible to extend sdcardio to use espsdcard on compatible boards; this new module is just a wrapper for some IDF ESP library;
  • JPEG support; ESP32-S3 contains a hardware JPEG decoder. I'm just using it :)
  • fonts - couldn't make displayio stable enough so font support wasn't possible for this board without it; also, keep in mind that this particular board is an AMOLED board, 2.41" only and 600x450 so regular fonts would be too small (but maybe it's just an excuse...); I'm planning to work on displayio integration in the future (on the current font support too)
  • RM690B0 support - I know that there's LILYGO T4 S3 board with the same display driver, haven't heard about any other; I believe that one would benefit from this port; BTW, both devices have the same USB ID, but Waveshare's one has more hardware "addons"
  • I believe so. The code that is using hardware JPEG decoding capability could be optional (IFDEF or something). Do you have any specific suggestions?

I could progress with this but I'd need some directions, if you don't mind.

@ppsx
Copy link
Author

ppsx commented Feb 1, 2026

Thanks again for your feedback, @dhalbert.

  • espsdcard: I removed this custom module entirely. After further testing, I found that the standard sdcardio module, when properly configured (20MHz baudrate and VFS optimization), achieves ~645 KB/s read speeds. This is parity with the native driver performance, so no custom C code or backend integration is needed for SD support anymore.

  • JPEG support: I have removed the custom esp_jpeg shim. I am now using the standard jpegio module which leverages the ESP32-S3 hardware decoder. To resolve the color issues, I updated the driver's blit function to accept a dest_is_swapped argument. This allows the hardware decoder's Big-Endian output to be DMA'd directly to the display without expensive software swapping, maintaining high performance using standard modules.

  • Fonts & RM690B0 support: I acknowledge that a standalone driver with built-in fonts is not idiomatic. However, I ask that you consider accepting this as a board-specific optimized driver for the following reasons:

    • Performance: Benchmarks show this driver is ~40x faster for primitives (e.g., circles) and significantly faster for text than the generic implementation.
    • Hardware Constraints: The ESP32-S3 has a hard limit of ~30 lines per DMA transfer. This driver implements complex buffer chunking strategies to manage this fragmentation and avoid ESP_ERR_NO_MEM, which would be difficult to abstract cleanly into BusDisplay without affecting other ports.
    • Synchronization: The driver uses a specific semaphore-based synchronization (instead of standard busy-waits) to eliminate tearing on this specific panel. My goal is to enable support for this hardware now, and I am open to migrating specific features to displayio in future PRs as the core evolves to handle these specific DMA/memory constraints.
  • Image Converter: Functionality removed. I replaced it with jpegio for JPEGs and a new optimized C-level helper convert_bmp for BMPs that handles format conversion and endian-swapping in a single pass.

@ppsx ppsx requested a review from dhalbert February 1, 2026 18:14
Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

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

I think you are going the right direction in using existing parts of CircuitPython. I'm glad you done a bunch of testing on this. Please come to us sooner to make sure you are taking the best high level approach.

Before adding sdcardio try sdioio in one bit mode. That is already implemented in espressif and I believe works for SPI sdcards. (That's why sdcardio isn't already implemented.)

I don't like the rm690b0 module because it is doing too much outside. Board specific stuff can be isolated to the board's directory but I don't think you actually need that here. Please start with adding an analog to FourWire for QSPI displays and get displayio working (even if it is slow).

Once we have that, we can talk about making it work faster.

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.

3 participants