Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
bb222a7
RM690B0 driver for Waveshare ESP32-S3 AMOLED 2.41"
ppsx Jan 30, 2026
76caacc
Merge branch '10.0.x' into rm690b0
ppsx Jan 30, 2026
9991543
Pre-commit hook fixes (1)
ppsx Jan 30, 2026
9f5c7f0
Copilot suggested changes (after verification)
ppsx Jan 30, 2026
42b7eb9
Typo fix
ppsx Jan 30, 2026
c232b45
Drop espsdcard in favour of sdcardio with standard API
ppsx Jan 31, 2026
c37c43c
Pre-commit hook fixes
ppsx Jan 31, 2026
3cfebc2
Cleanup
ppsx Jan 31, 2026
0aba2d2
ESP_JPEG location
ppsx Jan 31, 2026
83b925c
Get rid of image_converter
ppsx Feb 1, 2026
824ba52
Phase 1: migrate from custom sdcardio to sdioio
ppsx Feb 6, 2026
24f5a0e
Phase 2: add qspibus module for ESP32-S3 displays
ppsx Feb 6, 2026
4e58173
qspibus/displayio: stabilize RM690B0 refresh and deinit
ppsx Feb 6, 2026
4012d93
Merge branch 'phase3-displayio-finalize' into rm690b0-displayio
ppsx Feb 6, 2026
0bc16e1
Phase 4: remove standalone rm690b0 module and keep displayio path
ppsx Feb 6, 2026
4c0c365
Merge phase4-remove-standalone into rm690b0-displayio
ppsx Feb 6, 2026
1a438bd
Phase 5: optimize qspibus displayio transfer path
ppsx Feb 6, 2026
bfef472
Merge phase5-displayio-optimization into rm690b0-displayio
ppsx Feb 6, 2026
d5774f6
Phase 6: add final v2.0 changelog docs
ppsx Feb 6, 2026
0650ab1
Update: QSPBus API
ppsx Feb 7, 2026
d2680d5
Cleanup
ppsx Feb 7, 2026
8da0da6
Cleanup
ppsx Feb 7, 2026
5a5eec6
Cleanup
ppsx Feb 7, 2026
0621d5e
More cleanup
ppsx Feb 7, 2026
5946dd2
Update ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c
ppsx Feb 7, 2026
cb91159
Update shared-bindings/qspibus/QSPIBus.c
ppsx Feb 7, 2026
d5723ae
Update ports/espressif/common-hal/qspibus/QSPIBus.c
ppsx Feb 7, 2026
52c4417
Update shared-bindings/qspibus/QSPIBus.c
ppsx Feb 7, 2026
cfc6d1b
Renamed CIRCUITPY_ESP32_CAMERA -> CIRCUITPY_CAMERA
ppsx Feb 7, 2026
1c28d49
Fixed Copilot findings
ppsx Feb 7, 2026
2d11d9d
Fixed 3/4 of Copilot suggestions
ppsx Feb 7, 2026
14afb73
Fix in QSPIBus.c
ppsx Feb 7, 2026
5c4e9f4
Fix in pins.c
ppsx Feb 7, 2026
0a96f3c
More fixes
ppsx Feb 7, 2026
a754bd1
Update locale/circuitpython.pot
ppsx Feb 7, 2026
3f5ffcc
Another fix in QSPIBus.c
ppsx Feb 7, 2026
9483936
Almost there...
ppsx Feb 7, 2026
3a9305a
Fixes: QSPI
ppsx Feb 8, 2026
f8a01a5
Removed dead code
ppsx Feb 8, 2026
bcbf2cd
Update ports/espressif/common-hal/qspibus/QSPIBus.c
ppsx Feb 8, 2026
964c30b
Fix in QSPIBus.c
ppsx Feb 8, 2026
53a390d
Update locale/circuitpython.pot
ppsx Feb 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions locale/circuitpython.pot
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,10 @@ msgstr ""
msgid "Baudrate not supported by peripheral"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "Begin transaction first"
msgstr ""

#: shared-module/busdisplay/BusDisplay.c
#: shared-module/framebufferio/FramebufferDisplay.c
msgid "Below minimum frame rate"
Expand Down Expand Up @@ -701,6 +705,10 @@ msgstr ""
msgid "Buffer too small"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "Bus in display transaction"
msgstr ""

#: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c
#: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c
#: ports/nordic/common-hal/paralleldisplaybus/ParallelBus.c
Expand Down Expand Up @@ -999,6 +1007,10 @@ msgstr ""
msgid "Failed to allocate %q buffer"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "Failed to allocate DMA buffers"
msgstr ""

#: ports/espressif/common-hal/wifi/__init__.c
msgid "Failed to allocate Wifi memory"
msgstr ""
Expand Down Expand Up @@ -1036,6 +1048,10 @@ msgstr ""
msgid "Failed to create continuous channels: not found"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "Failed to create semaphore"
msgstr ""

#: ports/espressif/common-hal/audioio/AudioOut.c
msgid "Failed to enable continuous"
msgstr ""
Expand Down Expand Up @@ -1586,6 +1602,10 @@ msgstr ""
msgid "No out in program"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "No pending command"
msgstr ""

#: ports/atmel-samd/common-hal/busio/I2C.c
#: ports/espressif/common-hal/busio/I2C.c
#: ports/mimxrt10xx/common-hal/busio/I2C.c ports/nordic/common-hal/busio/I2C.c
Expand Down Expand Up @@ -1770,6 +1790,11 @@ msgstr ""
msgid "Packet buffers for an SPI transfer must have the same length."
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
#, c-format
msgid "Panel IO init failed: %d"
msgstr ""

#: shared-module/jpegio/JpegDecoder.c
msgid "Parameter error"
msgstr ""
Expand Down Expand Up @@ -1875,6 +1900,28 @@ msgstr ""
msgid "Pull not used when direction is output."
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "QSPI DMA buffers unavailable"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "QSPI color timeout"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "QSPI command timeout"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
#, c-format
msgid "QSPI send color failed: %d"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
#, c-format
msgid "QSPI send failed: %d"
msgstr ""

#: ports/raspberrypi/common-hal/countio/Counter.c
msgid "RISE_AND_FALL not available on this chip"
msgstr ""
Expand Down Expand Up @@ -1996,6 +2043,11 @@ msgstr ""
msgid "SDIO Init Error %x"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
#, c-format
msgid "SPI bus init failed: %d"
msgstr ""

#: ports/espressif/common-hal/busio/SPI.c
msgid "SPI configuration failed"
msgstr ""
Expand Down Expand Up @@ -3013,6 +3065,10 @@ msgstr ""
msgid "cross is defined for 1D arrays of length 3"
msgstr ""

#: ports/espressif/common-hal/qspibus/QSPIBus.c
msgid "Data buffer is null"
msgstr ""

#: extmod/ulab/code/scipy/optimize/optimize.c
msgid "data must be iterable"
msgstr ""
Expand Down
3 changes: 3 additions & 0 deletions ports/espressif/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,9 @@ endif
ifneq ($(CIRCUITPY_PARALLELDISPLAYBUS),0)
ESP_IDF_COMPONENTS_LINK += esp_lcd
endif
ifneq ($(CIRCUITPY_QSPIBUS),0)
ESP_IDF_COMPONENTS_LINK += esp_lcd
endif
ifneq ($(CIRCUITPY_USB_DEVICE),0)
ESP_IDF_COMPONENTS_LINK += usb
endif
Expand Down
8 changes: 8 additions & 0 deletions ports/espressif/boards/waveshare_esp32_s3_amoled_241/board.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha
//
// SPDX-License-Identifier: MIT

#include "supervisor/board.h"

void board_init(void) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha
//
// SPDX-License-Identifier: MIT

#pragma once

#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3-Touch-AMOLED-2.41"
#define MICROPY_HW_MCU_NAME "ESP32S3"

// USB identifiers
#define USB_VID 0x303A
#define USB_PID 0x82CE
#define USB_MANUFACTURER "Waveshare"
#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-2.41"

// I2C bus - Disabled on boot to avoid conflicts. User must manually initialize I2C.
#define CIRCUITPY_BOARD_I2C (0)
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO48, .sda = &pin_GPIO47}}

// QSPI display refresh buffer: 2048 uint32_t words = 8KB on stack.
// ESP32-S3 main task stack is 24KB; verified safe with this board.
#define CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE (2048)

// AMOLED Display (displayio + qspibus path)
#define CIRCUITPY_BOARD_DISPLAY (0)
#define CIRCUITPY_LCD_CS (&pin_GPIO9)
#define CIRCUITPY_LCD_CLK (&pin_GPIO10)
#define CIRCUITPY_LCD_D0 (&pin_GPIO11)
#define CIRCUITPY_LCD_D1 (&pin_GPIO12)
#define CIRCUITPY_LCD_D2 (&pin_GPIO13)
#define CIRCUITPY_LCD_D3 (&pin_GPIO14)
#define CIRCUITPY_LCD_RESET (&pin_GPIO21)
#define CIRCUITPY_LCD_POWER (&pin_GPIO16)
#define CIRCUITPY_LCD_POWER_ON_LEVEL (1) // GPIO level: 1=high, 0=low

// No default SPI bus — SD card uses SDIO, display uses QSPI.
#define CIRCUITPY_BOARD_SPI (0)

// Default UART bus
#define DEFAULT_UART_BUS_RX (&pin_GPIO44)
#define DEFAULT_UART_BUS_TX (&pin_GPIO43)
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha
#
# SPDX-License-Identifier: MIT

CIRCUITPY_CREATOR_ID = 0x57415645 # 'WAVE' (Waveshare)
CIRCUITPY_CREATION_ID = 0x41323431 # 'A241' (AMOLED 2.41)

# USB identifiers - from Arduino pins_arduino.h
USB_VID = 0x303A
USB_PID = 0x82CE
USB_MANUFACTURER = "Waveshare"
USB_PRODUCT = "ESP32-S3-Touch-AMOLED-2.41"

IDF_TARGET = esp32s3

# Flash configuration - 16MB QSPI Flash
CIRCUITPY_ESP_FLASH_SIZE = 16MB
CIRCUITPY_ESP_FLASH_MODE = qio
CIRCUITPY_ESP_FLASH_FREQ = 80m

# PSRAM configuration - 8MB Octal PSRAM
CIRCUITPY_ESP_PSRAM_SIZE = 8MB
CIRCUITPY_ESP_PSRAM_MODE = opi
CIRCUITPY_ESP_PSRAM_FREQ = 80m

OPTIMIZATION_FLAGS = -Os

# QSPI bus for RM690B0 AMOLED display
CIRCUITPY_QSPIBUS = 1
CIRCUITPY_PARALLELDISPLAYBUS = 0

# No camera on this board
CIRCUITPY_ESPCAMERA = 0

# Capacitive touch not available; board uses I2C touch controller
CIRCUITPY_TOUCHIO = 0

# SD card via SDMMC interface
CIRCUITPY_SDIOIO = 1
100 changes: 100 additions & 0 deletions ports/espressif/boards/waveshare_esp32_s3_amoled_241/pins.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha
//
// SPDX-License-Identifier: MIT

#include "py/obj.h"
#include "py/mphal.h"
#include "shared-bindings/board/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"

static const mp_rom_map_elem_t board_module_globals_table[] = {
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS

// =================================================================
// ONBOARD PERIPHERALS - Functional Names
// =================================================================

// Boot/Control/Battery/Display Power
// NOTE: GPIO16 is shared between battery control circuitry and LCD power
// (see CIRCUITPY_QSPIBUS_PANEL_POWER_PIN in mpconfigboard.h).
{ MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) },
{ MP_ROM_QSTR(MP_QSTR_KEY_BAT), MP_ROM_PTR(&pin_GPIO15) },
{ MP_ROM_QSTR(MP_QSTR_BAT_CONTROL), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_LCD_POWER), MP_ROM_PTR(&pin_GPIO16) },
{ MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO17) },

// I2C Bus (shared by Touch, RTC, IMU, IO Expander)
// NOTE: board.I2C auto-initialization is disabled (CIRCUITPY_BOARD_I2C=0)
// to avoid boot conflicts. Users must manually create I2C bus:
// i2c = busio.I2C(board.SCL, board.SDA)
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO47) },
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO48) },

// Touch Panel (FT6336U on I2C)
{ MP_ROM_QSTR(MP_QSTR_TP_SDA), MP_ROM_PTR(&pin_GPIO47) },
{ MP_ROM_QSTR(MP_QSTR_TP_SCL), MP_ROM_PTR(&pin_GPIO48) },
{ MP_ROM_QSTR(MP_QSTR_TP_RESET), MP_ROM_PTR(&pin_GPIO3) },

// RTC (PCF85063 on I2C)
{ MP_ROM_QSTR(MP_QSTR_RTC_SDA), MP_ROM_PTR(&pin_GPIO47) },
{ MP_ROM_QSTR(MP_QSTR_RTC_SCL), MP_ROM_PTR(&pin_GPIO48) },

// IMU (QMI8658 on I2C)
{ MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO47) },
{ MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO48) },

// I/O Expander (TCA9554 on I2C)
{ MP_ROM_QSTR(MP_QSTR_EXIO_SDA), MP_ROM_PTR(&pin_GPIO47) },
{ MP_ROM_QSTR(MP_QSTR_EXIO_SCL), MP_ROM_PTR(&pin_GPIO48) },

// USB
{ MP_ROM_QSTR(MP_QSTR_USB_D_N), MP_ROM_PTR(&pin_GPIO19) },
{ MP_ROM_QSTR(MP_QSTR_USB_D_P), MP_ROM_PTR(&pin_GPIO20) },

// UART
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) },

// QSPI Display (RM690B0) - canonical generic LCD aliases.
{ MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_LCD_D0), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_LCD_D1), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_LCD_D2), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_LCD_D3), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(&pin_GPIO21) },

// Display Aliases
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_CS), MP_ROM_PTR(&pin_GPIO9) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_SCK), MP_ROM_PTR(&pin_GPIO10) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_D0), MP_ROM_PTR(&pin_GPIO11) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_D1), MP_ROM_PTR(&pin_GPIO12) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_D2), MP_ROM_PTR(&pin_GPIO13) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_D3), MP_ROM_PTR(&pin_GPIO14) },
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_RST), MP_ROM_PTR(&pin_GPIO21) },

// SD Card (SDIO / SDMMC)
{ MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO4) },
{ MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_GPIO5) },
{ MP_ROM_QSTR(MP_QSTR_SDIO_D0), MP_ROM_PTR(&pin_GPIO6) },
{ MP_ROM_QSTR(MP_QSTR_SDIO_D3), MP_ROM_PTR(&pin_GPIO2) },

// =================================================================
// GENERAL PURPOSE I/O (IOxx - Espressif Convention)
// =================================================================
// Only pins NOT dedicated to onboard peripherals are exposed here.
// Use functional names above for dedicated pins (e.g., SDA, SD_CS).

{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, // BOOT button (available when not holding BOOT)
{ MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, // Available
{ MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, // TP_RESET (available if touch not used)
{ MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, // Available
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, // Available
{ MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, // Available
{ MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, // Available
{ MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, // Available
{ MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, // Available
{ MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, // Available
{ MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, // Available
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
33 changes: 33 additions & 0 deletions ports/espressif/boards/waveshare_esp32_s3_amoled_241/sdkconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#
# Configuration file for the Waveshare ESP32-S3 Touch AMOLED 2.41
#

# PSRAM Configuration
CONFIG_SPIRAM=y
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_USE_MALLOC=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM_MEMTEST=y
CONFIG_SPIRAM_CLK_IO=39
CONFIG_SPIRAM_CS_IO=38

# Performance and Cache
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y

# Default flash settings for this board
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-16MB.csv"
CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-16MB.csv"

# Networking
CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-amoled"

# Disable USB-Serial/JTAG console - CircuitPython uses TinyUSB (USB OTG) for REPL
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=n

# Enable .app_desc structure
CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16
Loading
Loading