QSPI bus driver and Waveshare ESP32-S3 Touch AMOLED 2.41" board support#10844
QSPI bus driver and Waveshare ESP32-S3 Touch AMOLED 2.41" board support#10844ppsx wants to merge 27 commits intoadafruit:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request introduces a new QSPI (Quad-SPI) bus driver for CircuitPython, specifically to support the Waveshare ESP32-S3 Touch AMOLED 2.41" display which uses the RM690B0 controller. The implementation follows CircuitPython's established display bus architecture patterns.
Changes:
- Adds a new
qspibusmodule providing QSPI bus protocol support analogous tofourwirefor standard SPI - Implements ESP32-S3 specific QSPI bus driver using ESP-IDF's LCD panel IO API with DMA and ISR support
- Adds board definition for Waveshare ESP32-S3 Touch AMOLED 2.41" with comprehensive pin mappings
- Optimizes display buffer sizes for QSPI panels to reduce command/window overhead
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
shared-bindings/qspibus/__init__.c |
Python module definition for qspibus |
shared-bindings/qspibus/__init__.h |
Module header with imports |
shared-bindings/qspibus/QSPIBus.c |
Python bindings for QSPIBus class with send(), write_command(), write_data() methods |
shared-bindings/qspibus/QSPIBus.h |
QSPIBus class interface declaration |
ports/espressif/common-hal/qspibus/QSPIBus.c |
ESP32-S3 QSPI implementation using ESP-IDF LCD panel IO with DMA buffers and ISR callbacks |
ports/espressif/common-hal/qspibus/QSPIBus.h |
ESP32-S3 QSPI bus structure definition |
ports/espressif/common-hal/qspibus/__init__.c |
Empty implementation file (placeholder) |
ports/espressif/common-hal/qspibus/__init__.h |
Empty header file (placeholder) |
shared-module/displayio/bus_core.c |
Integrates QSPI bus into displayio bus abstraction |
shared-module/displayio/__init__.h |
Adds QSPI bus to primary display bus union |
shared-module/displayio/__init__.c |
Adds QSPI bus cleanup to display release path |
shared-module/busdisplay/BusDisplay.c |
QSPI-specific buffer optimization for efficient refresh |
py/circuitpy_mpconfig.mk |
Build flag for QSPI bus support |
py/circuitpy_mpconfig.h |
QSPI display buffer size configuration |
py/circuitpy_defns.mk |
Build pattern matching for qspibus module |
ports/espressif/Makefile |
Links esp_lcd component when QSPIBUS enabled |
ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h |
Board configuration with pin definitions and buffer size |
ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.mk |
Board build configuration enabling QSPIBUS |
ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c |
Comprehensive pin mapping with functional names |
ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c |
Empty board initialization |
ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig |
ESP-IDF SDK configuration for PSRAM and peripherals |
locale/circuitpython.pot |
Translation strings for QSPI error messages |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
tannewt
left a comment
There was a problem hiding this comment.
This is definitely getting closer! Please prevent additional error messages from being added. You likely can reuse existing ones. Please also iterate with copilot on your own fork before making a PR.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (2)
locale/circuitpython.pot:922
- The error message "Data buffer is null" is added to the locale file but is never used in the codebase. Either remove this unused error message from the locale file or add the corresponding validation check in the code where it's needed.
#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "Data buffer is null"
msgstr ""
ports/espressif/common-hal/qspibus/QSPIBus.c:359
- The ternary operator
CIRCUITPY_LCD_POWER_ON_LEVEL ? 1 : 0is redundant since CIRCUITPY_LCD_POWER_ON_LEVEL is already defined as either 0 or 1 (see lines 32-34). Simplify this to justCIRCUITPY_LCD_POWER_ON_LEVELto make the code clearer and avoid potential confusion.
gpio_set_level((gpio_num_t)self->power_pin, CIRCUITPY_LCD_POWER_ON_LEVEL ? 1 : 0);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 22 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 22 out of 22 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Thank you @tannewt for your feedback. I've implemented requested changes and did a couple of sessions with Copilot. Now the code needs some more professional view than me or Copilot :) |
|
Please make sure the automated tests also pass. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.
Comments suppressed due to low confidence (1)
ports/espressif/common-hal/qspibus/QSPIBus.c:467
- Inconsistent indentation: this line uses 3 spaces instead of 4 spaces for indentation. All other if statements in this function use 4 spaces.
if (!self->has_pending_command) {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
py/circuitpy_mpconfig.h:407
- The comment says this value can be overridden “for larger buffers”, but
shared-module/busdisplay/BusDisplay.cenforces a hard maximum of 2048 words via_Static_assert. Either document the effective maximum here as well, or make the maximum configurable/port-specific so the documentation matches actual build constraints.
// QSPI display buffer size in uint32_t words for _refresh_area() VLA.
// Allocated on stack; boards should verify sufficient stack headroom.
// Default 512 words = 2KB. Override per-board for larger buffers.
#ifndef CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE
#define CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE (512)
#endif
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Align begin_transaction() with bus_free() by delegating to it, so transfer_in_progress and has_pending_command are checked before entering a transaction. This prevents silently discarding a staged write_command() or starting a transaction during active DMA. - Regenerate locale/circuitpython.pot to remove stale "Data buffer is null" entry left over from the previous round of error message reuse.
#1) * Initial plan * Fix stale and missing locale entries for qspibus Co-authored-by: ppsx <7107135+ppsx@users.noreply.github.com> * qspibus: three low-cost cleanups consistent with CircuitPython conventions Co-authored-by: ppsx <7107135+ppsx@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: ppsx <7107135+ppsx@users.noreply.github.com> Co-authored-by: ppsx <ppsx@users.noreply.github.com>
Refactor display bus region-update command emission into a shared helper with optional transaction management. Keep the existing public path unchanged, and add a QSPIBus-only entrypoint that can send region commands without nesting begin/end transaction calls. Also remove the TileGrid 16bpp+Palette fast path so fill_area uses the generic path, and fix indentation in QSPIBus write_data.
|
You'll need to add |
|
@tannewt - done. |
tannewt
left a comment
There was a problem hiding this comment.
Thanks for continuing to iterate on this. I'm excited by overlapping sending pixels and computing them.
ports/espressif/boards/waveshare_esp32_s3_amoled_241/mpconfigboard.h
Outdated
Show resolved
Hide resolved
tannewt
left a comment
There was a problem hiding this comment.
Ok, I've got a better idea of how this works and think there are just a couple small tweaks to make to simplify things. Thanks!
|
Thank you, @tannewt, for your professional approach. I learned a lot during this PR :) |
tannewt
left a comment
There was a problem hiding this comment.
Very close. One other cleanup to do.
|
|
||
| void displayio_display_bus_set_region_to_update(displayio_display_bus_t *self, displayio_display_core_t *display, displayio_area_t *area) { | ||
| _displayio_display_bus_send_region_commands(self, display, area, true); | ||
| } |
There was a problem hiding this comment.
Actually revert the above. You don't need manage_transaction any more. (Please review LLM changes thoroughly before asking me to.)
There was a problem hiding this comment.
Thank you and I'm sorry.
I removed the manage_transactions parameter from _displayio_display_bus_send_region_commands - it was always called with true, so the conditionals were unnecessary. All begin_transaction/end_transaction calls are now unconditional.
Add qspibus display bus and Waveshare ESP32-S3 Touch AMOLED 2.41" board support
Summary
Hardware