Repository navigation
Conversation
New board env for the 3.5" ESP32-S3 ST77922 (320x480) module: - display via the new Arduino_ST77922_1L4 driver (DisplayDrivers submodule) - TFT_DC=-1 / TFT_IPS=0 to stop pre_compiler.h's CYD defaults clobbering TFT_CS/TFT_SCLK - new TOUCH_CTRL_ST77922 driver (I2C 0x55, 16-bit regs, whole-block read) - SD_MMC 4-bit, backlight PWM, WS2812 LED, audio amp held off Verified on hardware: display, touch, SD, all four rotations. Env is left commented out of default_envs and the CI matrix. Unverified: audio, battery sense, deep sleep. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
GPIO 8 is a 1:2 divider off the LiPo rail. Found by an ADC scan of the unclaimed pins and checked against a multimeter (2.007 V x 2 = 4.01 V vs 3.99-4.00 V measured while charging). Default ANALOG_BAT_MULTIPLIER of 2.0 applies, so only ANALOG_BAT_PIN=8 is needed. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
powerOff() was copied from ES3C28P and overrode Launcher's default, which enables the GPIO0 wake source. It called esp_deep_sleep_start() with no wake source, so only a reset or power cycle could bring the board back, and the backlight pad was left to float. Now enable ext0 wake on GPIO0 (BOOT), latch the backlight pin low for the sleep and release it in _setup_gpio(). Touch cannot wake deep sleep: its INT (GPIO47) is not an RTC pad. Verified on hardware: screen fully dark, BOOT wakes, touch does not. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Launcher has no sound output on any board; the codec and amp are only kept quiet at boot. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Remove the ST77922_BRINGUP_TEST / ST77922_TOUCH_DEBUG guards, refresh the stale "not buildable yet" header, and enable the env in the CI matrix now that it builds and is verified on hardware (per boards/NEW_BOARD_GUIDE.md). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This was referenced Nov 9, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds support for the 3.5" ESP32-S3 320x480 touch module sold as the LCDwiki
ES3C35P (also rebadged, e.g. Hosyond "ESP32-S3 Touchscreen Module 3.5"" and
AliExpress "cheap black display" listings). Requested in #434. Depends on bmorcelli/DisplayDrivers#3 (the display driver).
This panel is not covered by any existing databus: the ST77922 is driven over
quad-SPI with no DC pin, and wants register writes on one line but pixel
data on four. Arduino_GFX's
Arduino_ESP32QSPIsends every phase on fourlines, so it cannot drive the panel. The change adds:
Arduino_ST77922_1L4(TFT_DATABUS_N=6,TFT_DISPLAY_DRIVER_N=52),an own-bus raw ESP-IDF
spi_masterdriver. Lives in theDisplayDriverssubmodule (separate PR, linked below).
USE_CANVAS=1handles rotation insoftware, since this panel's MADCTL does not remap addressing.
TOUCH_CTRL_ST77922branch insrc/hal/inputs/touch.cpp.The touch block is built into the same IC (I2C
0x55, 16-bit big-endianregister addresses). It is not FT6x36-compatible, despite appearing as
"FT6336G-compatible" in some third-party notes; the FT6X36 path reads the
wrong registers on this chip.
boards/lcdwiki-es3c35p/(platformio.ini,interface.cpp,connections.md), registered in the CI matrix;default_envsentry addedcommented-out like every other board.
Nothing in
src/outsidetouch.cppis changed, and thetouch.cppadditionis entirely behind
TOUCH_CTRL_ST77922.Hardware / links
78/xiaozhi-esp32boards/lcdwiki-es3c35p/; https://tinkerpad.co.uk/esp32-s3-35-lcd.htmlPinout (all documented in
boards/lcdwiki-es3c35p/connections.md):display CS=10 SCLK=12 D0=11 D1=13 D2=14 D3=9 BL=41 (no RST pin);
touch SDA=38 SCL=39 RST=48 INT=47; SD native 4-bit SDIO CLK=5 CMD=4 D0=6 D1=7 D2=2 D3=3;
battery sense GPIO 8; WS2812 on 40; BOOT=0.
Pitfalls worth a reviewer's attention
TFT_DC=-1/TFT_IPS=0in the board ini are load-bearing.include/pre_compiler.h's "CYD defaults" block silently redefinesTFT_CS/TFT_SCLK(to 15/14) whenever a board defines none ofTFT_DC,TFT_IPS,TFT_COL_OFS*orTFT_MOSI. A QSPI board has no DC or MOSI pin,so without these two flags the SPI bus init fails ("not using iomux pins").
This cost most of the bring-up time; it may be worth a comment or a different
guard in
pre_compiler.has a follow-up (not changed here).maxTouches * 8bytes). Reading only the first record leaves the controller returning a
stale point forever.
it is pulsed (done once in
_setup_gpio()). The display does not need it.powerOff(): touch cannot wake deep sleep here (INT is GPIO47, not an RTCpad), so BOOT/GPIO0 (ext0) is the only wake source. The board's
powerOff()enables it, switches the backlight off and latches the pin low for the sleep,
and
_setup_gpio()releases the latch on boot.Verification
Tested on one physical unit (AliExpress purchase above) running the image built
from this branch, flashed with
esptoolat0x0(merged image).Build:
pio run -e lcdwiki-es3c35psucceeds on this branch rebased ontocurrent
main(the full test matrix below was run on the same code beforerebasing onto two unrelated upstream Heltec commits; after the rebase the board
was reflashed and re-checked for boot, touch and brightness). Firmware app
image is about 1.42 MB (8.5 % of the 16 MB flash); RAM use 26.4 %.
78/xiaozhi-esp32v2.5.2lcdwiki-es3c35pmerged image (10.2 MB, SHA-256 matched the release'sSHA256SUMS)0x0000) fails the install check with "Flash Read Failed" instead of being booted -- expected behaviour, not a port issueObserved once, not reproduced: a single episode of touch moving 1-2 menu
entries too far per tap during a long test session (USB plus charging LiPo).
It cleared after a full power cycle (battery and USB removed) and has not
recurred; cause unknown, possibly transient electrical noise while charging.
Observed, not specific to this board: uploading a 10 MB file through the
Launcher web file manager failed with
Upload failed: Upload receive failed(the receive loop got a dropped connection mid-body; serial log shows no panic,
watchdog or reboot). A ~1 MB upload through the same path succeeded. The SD
card, flash and image checks were never reached. Copying the file onto the SD
card directly avoids the web path.
Not tested: deep sleep on battery alone with USB removed; sleep current;
audio (the ES8311 codec / SC8002B amp are only held quiet -- Launcher has no
sound output on any board); only a single hardware unit.
Regression check on shared code:
touch.cppandDisplayDriversare shared, soES3C28PandES3C40P(same family, standard-SPI panels sharing the touch andDisplayDrivers code) were also built from this branch: both
pio runbuildssucceed. These were build checks only; they were not flashed or run.
Merge order
Arduino_ST77922_1L4and the bus-6 wiring).lib/DisplayDriverssubmodule pointer to that commit.Until step 1 lands, CI on this PR cannot fetch the submodule commit.
If the DisplayDrivers PR is squash-merged, its commit hash changes, so the
submodule pointer here needs updating to the merged hash before this merges.
This PR is therefore opened as a draft until then.
Provenance / licensing note
The ST77922 init-command table is the one from the board vendor's published
example (https://github.com/ydedox/st77922, Example_01), which carries no
license file. It is register data rather than code, and confirmed working on
hardware, but flagging it so the maintainer can decide whether they are
comfortable with it or want it sourced from the MIT-licensed
78/xiaozhi-esp32equivalent instead. All other code is original to this PR.Another contributor (@javaoverride, in #434) has independently got this board
working with a different approach (Arduino_GFX driver files and submodule edits).
This PR does not use their code; happy to coordinate or merge efforts.
Closes #434
🤖 Generated with Claude Code