Skip to content

Commit 89c8186

Browse files
committed
QSPI bus driver and RM690B0 display driver for Waveshare ESP32-S3 AMOLED 2.41
1 parent 8fb29d9 commit 89c8186

22 files changed

Lines changed: 1340 additions & 0 deletions

File tree

locale/circuitpython.pot

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,10 @@ msgstr ""
646646
msgid "Baudrate not supported by peripheral"
647647
msgstr ""
648648

649+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
650+
msgid "Begin transaction first"
651+
msgstr ""
652+
649653
#: shared-module/busdisplay/BusDisplay.c
650654
#: shared-module/framebufferio/FramebufferDisplay.c
651655
msgid "Below minimum frame rate"
@@ -712,6 +716,10 @@ msgstr ""
712716
msgid "Buffer too small"
713717
msgstr ""
714718

719+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
720+
msgid "Bus in display transaction"
721+
msgstr ""
722+
715723
#: ports/atmel-samd/common-hal/paralleldisplaybus/ParallelBus.c
716724
#: ports/espressif/common-hal/paralleldisplaybus/ParallelBus.c
717725
#: ports/nordic/common-hal/paralleldisplaybus/ParallelBus.c
@@ -906,6 +914,10 @@ msgstr ""
906914
msgid "Data 0 pin must be byte aligned"
907915
msgstr ""
908916

917+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
918+
msgid "Data buffer is null"
919+
msgstr ""
920+
909921
#: shared-module/jpegio/JpegDecoder.c
910922
msgid "Data format error (may be broken data)"
911923
msgstr ""
@@ -1017,6 +1029,10 @@ msgstr ""
10171029
msgid "Failed to allocate %q buffer"
10181030
msgstr ""
10191031

1032+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
1033+
msgid "Failed to allocate DMA buffers"
1034+
msgstr ""
1035+
10201036
#: ports/espressif/common-hal/wifi/__init__.c
10211037
msgid "Failed to allocate Wifi memory"
10221038
msgstr ""
@@ -1054,6 +1070,10 @@ msgstr ""
10541070
msgid "Failed to create continuous channels: not found"
10551071
msgstr ""
10561072

1073+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
1074+
msgid "Failed to create semaphore"
1075+
msgstr ""
1076+
10571077
#: ports/espressif/common-hal/audioio/AudioOut.c
10581078
msgid "Failed to enable continuous"
10591079
msgstr ""
@@ -1599,6 +1619,10 @@ msgstr ""
15991619
msgid "No out in program"
16001620
msgstr ""
16011621

1622+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
1623+
msgid "No pending command"
1624+
msgstr ""
1625+
16021626
#: ports/atmel-samd/common-hal/busio/I2C.c
16031627
#: ports/espressif/common-hal/busio/I2C.c
16041628
#: ports/mimxrt10xx/common-hal/busio/I2C.c ports/nordic/common-hal/busio/I2C.c
@@ -1783,6 +1807,11 @@ msgstr ""
17831807
msgid "Packet buffers for an SPI transfer must have the same length."
17841808
msgstr ""
17851809

1810+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
1811+
#, c-format
1812+
msgid "Panel IO init failed: %d"
1813+
msgstr ""
1814+
17861815
#: shared-module/jpegio/JpegDecoder.c
17871816
msgid "Parameter error"
17881817
msgstr ""
@@ -1889,6 +1918,28 @@ msgstr ""
18891918
msgid "Pull not used when direction is output."
18901919
msgstr ""
18911920

1921+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
1922+
msgid "QSPI DMA buffers unavailable"
1923+
msgstr ""
1924+
1925+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
1926+
msgid "QSPI color timeout"
1927+
msgstr ""
1928+
1929+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
1930+
msgid "QSPI command timeout"
1931+
msgstr ""
1932+
1933+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
1934+
#, c-format
1935+
msgid "QSPI send color failed: %d"
1936+
msgstr ""
1937+
1938+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
1939+
#, c-format
1940+
msgid "QSPI send failed: %d"
1941+
msgstr ""
1942+
18921943
#: ports/raspberrypi/common-hal/countio/Counter.c
18931944
msgid "RISE_AND_FALL not available on this chip"
18941945
msgstr ""
@@ -2010,6 +2061,11 @@ msgstr ""
20102061
msgid "SDIO Init Error %x"
20112062
msgstr ""
20122063

2064+
#: ports/espressif/common-hal/qspibus/QSPIBus.c
2065+
#, c-format
2066+
msgid "SPI bus init failed: %d"
2067+
msgstr ""
2068+
20132069
#: ports/espressif/common-hal/busio/SPI.c
20142070
msgid "SPI configuration failed"
20152071
msgstr ""

ports/espressif/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,9 @@ endif
780780
ifneq ($(CIRCUITPY_PARALLELDISPLAYBUS),0)
781781
ESP_IDF_COMPONENTS_LINK += esp_lcd
782782
endif
783+
ifneq ($(CIRCUITPY_QSPIBUS),0)
784+
ESP_IDF_COMPONENTS_LINK += esp_lcd
785+
endif
783786
ifneq ($(CIRCUITPY_USB_DEVICE),0)
784787
ESP_IDF_COMPONENTS_LINK += usb
785788
endif
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
#include "supervisor/board.h"
6+
7+
void board_init(void) {
8+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
#pragma once
6+
7+
#define MICROPY_HW_BOARD_NAME "Waveshare ESP32-S3-Touch-AMOLED-2.41"
8+
#define MICROPY_HW_MCU_NAME "ESP32S3"
9+
10+
// USB identifiers
11+
#define USB_VID 0x303A
12+
#define USB_PID 0x82CE
13+
#define USB_MANUFACTURER "Waveshare"
14+
#define USB_PRODUCT "ESP32-S3-Touch-AMOLED-2.41"
15+
16+
// I2C bus - Disabled on boot to avoid conflicts. User must manually initialize I2C.
17+
#define CIRCUITPY_BOARD_I2C (0)
18+
#define CIRCUITPY_BOARD_I2C_PIN {{.scl = &pin_GPIO48, .sda = &pin_GPIO47}}
19+
20+
// QSPI display refresh buffer: 2048 uint32_t words = 8KB on stack.
21+
// ESP32-S3 main task stack is 24KB; verified safe with this board.
22+
#define CIRCUITPY_QSPI_DISPLAY_AREA_BUFFER_SIZE (2048)
23+
24+
// AMOLED Display (displayio + qspibus path)
25+
#define CIRCUITPY_BOARD_DISPLAY (0)
26+
#define CIRCUITPY_LCD_CS (&pin_GPIO9)
27+
#define CIRCUITPY_LCD_CLK (&pin_GPIO10)
28+
#define CIRCUITPY_LCD_D0 (&pin_GPIO11)
29+
#define CIRCUITPY_LCD_D1 (&pin_GPIO12)
30+
#define CIRCUITPY_LCD_D2 (&pin_GPIO13)
31+
#define CIRCUITPY_LCD_D3 (&pin_GPIO14)
32+
#define CIRCUITPY_LCD_RESET (&pin_GPIO21)
33+
#define CIRCUITPY_LCD_POWER (&pin_GPIO16)
34+
#define CIRCUITPY_LCD_POWER_ON_LEVEL (1) // GPIO level: 1=high, 0=low
35+
36+
// No default SPI bus — SD card uses SDIO, display uses QSPI.
37+
#define CIRCUITPY_BOARD_SPI (0)
38+
39+
// Default UART bus
40+
#define DEFAULT_UART_BUS_RX (&pin_GPIO44)
41+
#define DEFAULT_UART_BUS_TX (&pin_GPIO43)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
CIRCUITPY_CREATOR_ID = 0x57415645 # 'WAVE' (Waveshare)
6+
CIRCUITPY_CREATION_ID = 0x41323431 # 'A241' (AMOLED 2.41)
7+
8+
# USB identifiers - from Arduino pins_arduino.h
9+
USB_VID = 0x303A
10+
USB_PID = 0x82CE
11+
USB_MANUFACTURER = "Waveshare"
12+
USB_PRODUCT = "ESP32-S3-Touch-AMOLED-2.41"
13+
14+
IDF_TARGET = esp32s3
15+
16+
# Flash configuration - 16MB QSPI Flash
17+
CIRCUITPY_ESP_FLASH_SIZE = 16MB
18+
CIRCUITPY_ESP_FLASH_MODE = qio
19+
CIRCUITPY_ESP_FLASH_FREQ = 80m
20+
21+
# PSRAM configuration - 8MB Octal PSRAM
22+
CIRCUITPY_ESP_PSRAM_SIZE = 8MB
23+
CIRCUITPY_ESP_PSRAM_MODE = opi
24+
CIRCUITPY_ESP_PSRAM_FREQ = 80m
25+
26+
OPTIMIZATION_FLAGS = -Os
27+
28+
# QSPI bus for RM690B0 AMOLED display
29+
CIRCUITPY_QSPIBUS = 1
30+
CIRCUITPY_PARALLELDISPLAYBUS = 0
31+
32+
# No camera on this board
33+
CIRCUITPY_ESPCAMERA = 0
34+
35+
# Capacitive touch not available; board uses I2C touch controller
36+
CIRCUITPY_TOUCHIO = 0
37+
38+
# SD card via SDMMC interface
39+
CIRCUITPY_SDIOIO = 1
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2026 Przemyslaw Patrick Socha
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
#include "py/obj.h"
6+
#include "py/mphal.h"
7+
#include "shared-bindings/board/__init__.h"
8+
#include "shared-bindings/microcontroller/Pin.h"
9+
10+
static const mp_rom_map_elem_t board_module_globals_table[] = {
11+
CIRCUITPYTHON_BOARD_DICT_STANDARD_ITEMS
12+
13+
// =================================================================
14+
// ONBOARD PERIPHERALS - Functional Names
15+
// =================================================================
16+
17+
// Boot/Control/Battery/Display Power
18+
// NOTE: GPIO16 is shared between battery control circuitry and LCD power
19+
// (see CIRCUITPY_QSPIBUS_PANEL_POWER_PIN in mpconfigboard.h).
20+
{ MP_ROM_QSTR(MP_QSTR_BOOT), MP_ROM_PTR(&pin_GPIO0) },
21+
{ MP_ROM_QSTR(MP_QSTR_KEY_BAT), MP_ROM_PTR(&pin_GPIO15) },
22+
{ MP_ROM_QSTR(MP_QSTR_BAT_CONTROL), MP_ROM_PTR(&pin_GPIO16) },
23+
{ MP_ROM_QSTR(MP_QSTR_LCD_POWER), MP_ROM_PTR(&pin_GPIO16) },
24+
{ MP_ROM_QSTR(MP_QSTR_BAT_ADC), MP_ROM_PTR(&pin_GPIO17) },
25+
26+
// I2C Bus (shared by Touch, RTC, IMU, IO Expander)
27+
// NOTE: board.I2C auto-initialization is disabled (CIRCUITPY_BOARD_I2C=0)
28+
// to avoid boot conflicts. Users must manually create I2C bus:
29+
// i2c = busio.I2C(board.SCL, board.SDA)
30+
{ MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO47) },
31+
{ MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO48) },
32+
33+
// Touch Panel (FT6336U on I2C)
34+
{ MP_ROM_QSTR(MP_QSTR_TP_SDA), MP_ROM_PTR(&pin_GPIO47) },
35+
{ MP_ROM_QSTR(MP_QSTR_TP_SCL), MP_ROM_PTR(&pin_GPIO48) },
36+
{ MP_ROM_QSTR(MP_QSTR_TP_RESET), MP_ROM_PTR(&pin_GPIO3) },
37+
38+
// RTC (PCF85063 on I2C)
39+
{ MP_ROM_QSTR(MP_QSTR_RTC_SDA), MP_ROM_PTR(&pin_GPIO47) },
40+
{ MP_ROM_QSTR(MP_QSTR_RTC_SCL), MP_ROM_PTR(&pin_GPIO48) },
41+
42+
// IMU (QMI8658 on I2C)
43+
{ MP_ROM_QSTR(MP_QSTR_IMU_SDA), MP_ROM_PTR(&pin_GPIO47) },
44+
{ MP_ROM_QSTR(MP_QSTR_IMU_SCL), MP_ROM_PTR(&pin_GPIO48) },
45+
46+
// I/O Expander (TCA9554 on I2C)
47+
{ MP_ROM_QSTR(MP_QSTR_EXIO_SDA), MP_ROM_PTR(&pin_GPIO47) },
48+
{ MP_ROM_QSTR(MP_QSTR_EXIO_SCL), MP_ROM_PTR(&pin_GPIO48) },
49+
50+
// USB
51+
{ MP_ROM_QSTR(MP_QSTR_USB_D_N), MP_ROM_PTR(&pin_GPIO19) },
52+
{ MP_ROM_QSTR(MP_QSTR_USB_D_P), MP_ROM_PTR(&pin_GPIO20) },
53+
54+
// UART
55+
{ MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
56+
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) },
57+
58+
// QSPI Display (RM690B0) - canonical generic LCD aliases.
59+
{ MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_GPIO9) },
60+
{ MP_ROM_QSTR(MP_QSTR_LCD_CLK), MP_ROM_PTR(&pin_GPIO10) },
61+
{ MP_ROM_QSTR(MP_QSTR_LCD_D0), MP_ROM_PTR(&pin_GPIO11) },
62+
{ MP_ROM_QSTR(MP_QSTR_LCD_D1), MP_ROM_PTR(&pin_GPIO12) },
63+
{ MP_ROM_QSTR(MP_QSTR_LCD_D2), MP_ROM_PTR(&pin_GPIO13) },
64+
{ MP_ROM_QSTR(MP_QSTR_LCD_D3), MP_ROM_PTR(&pin_GPIO14) },
65+
{ MP_ROM_QSTR(MP_QSTR_LCD_RESET), MP_ROM_PTR(&pin_GPIO21) },
66+
67+
// Display Aliases
68+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_CS), MP_ROM_PTR(&pin_GPIO9) },
69+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_SCK), MP_ROM_PTR(&pin_GPIO10) },
70+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_D0), MP_ROM_PTR(&pin_GPIO11) },
71+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_D1), MP_ROM_PTR(&pin_GPIO12) },
72+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_D2), MP_ROM_PTR(&pin_GPIO13) },
73+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_D3), MP_ROM_PTR(&pin_GPIO14) },
74+
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_RST), MP_ROM_PTR(&pin_GPIO21) },
75+
76+
// SD Card (SDIO / SDMMC)
77+
{ MP_ROM_QSTR(MP_QSTR_SDIO_CLK), MP_ROM_PTR(&pin_GPIO4) },
78+
{ MP_ROM_QSTR(MP_QSTR_SDIO_CMD), MP_ROM_PTR(&pin_GPIO5) },
79+
{ MP_ROM_QSTR(MP_QSTR_SDIO_D0), MP_ROM_PTR(&pin_GPIO6) },
80+
{ MP_ROM_QSTR(MP_QSTR_SDIO_D3), MP_ROM_PTR(&pin_GPIO2) },
81+
82+
// =================================================================
83+
// GENERAL PURPOSE I/O (IOxx - Espressif Convention)
84+
// =================================================================
85+
// Only pins NOT dedicated to onboard peripherals are exposed here.
86+
// Use functional names above for dedicated pins (e.g., SDA, SD_CS).
87+
88+
{ MP_ROM_QSTR(MP_QSTR_IO0), MP_ROM_PTR(&pin_GPIO0) }, // BOOT button (available when not holding BOOT)
89+
{ MP_ROM_QSTR(MP_QSTR_IO1), MP_ROM_PTR(&pin_GPIO1) }, // Available
90+
{ MP_ROM_QSTR(MP_QSTR_IO3), MP_ROM_PTR(&pin_GPIO3) }, // TP_RESET (available if touch not used)
91+
{ MP_ROM_QSTR(MP_QSTR_IO7), MP_ROM_PTR(&pin_GPIO7) }, // Available
92+
{ MP_ROM_QSTR(MP_QSTR_IO8), MP_ROM_PTR(&pin_GPIO8) }, // Available
93+
{ MP_ROM_QSTR(MP_QSTR_IO18), MP_ROM_PTR(&pin_GPIO18) }, // Available
94+
{ MP_ROM_QSTR(MP_QSTR_IO40), MP_ROM_PTR(&pin_GPIO40) }, // Available
95+
{ MP_ROM_QSTR(MP_QSTR_IO41), MP_ROM_PTR(&pin_GPIO41) }, // Available
96+
{ MP_ROM_QSTR(MP_QSTR_IO42), MP_ROM_PTR(&pin_GPIO42) }, // Available
97+
{ MP_ROM_QSTR(MP_QSTR_IO45), MP_ROM_PTR(&pin_GPIO45) }, // Available
98+
{ MP_ROM_QSTR(MP_QSTR_IO46), MP_ROM_PTR(&pin_GPIO46) }, // Available
99+
};
100+
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#
2+
# Configuration file for the Waveshare ESP32-S3 Touch AMOLED 2.41
3+
#
4+
5+
# PSRAM Configuration
6+
CONFIG_SPIRAM=y
7+
CONFIG_SPIRAM_BOOT_INIT=y
8+
CONFIG_SPIRAM_USE_MALLOC=y
9+
CONFIG_SPIRAM_MODE_OCT=y
10+
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
11+
CONFIG_SPIRAM_RODATA=y
12+
CONFIG_SPIRAM_SPEED_80M=y
13+
CONFIG_SPIRAM_MEMTEST=y
14+
CONFIG_SPIRAM_CLK_IO=39
15+
CONFIG_SPIRAM_CS_IO=38
16+
17+
# Performance and Cache
18+
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
19+
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
20+
21+
# Default flash settings for this board
22+
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
23+
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="esp-idf-config/partitions-16MB.csv"
24+
CONFIG_PARTITION_TABLE_FILENAME="esp-idf-config/partitions-16MB.csv"
25+
26+
# Networking
27+
CONFIG_LWIP_LOCAL_HOSTNAME="waveshare-esp32-s3-amoled"
28+
29+
# Disable USB-Serial/JTAG console - CircuitPython uses TinyUSB (USB OTG) for REPL
30+
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=n
31+
32+
# Enable .app_desc structure
33+
CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16

0 commit comments

Comments
 (0)