Skip to content

Add ESP32-S3-Touch-LCD-1.47 port with landscape support - #148

Open
tsisar wants to merge 4 commits into
HermannBjorgvin:mainfrom
tsisar:feature/waveshare-lcd-147
Open

Add ESP32-S3-Touch-LCD-1.47 port with landscape support#148
tsisar wants to merge 4 commits into
HermannBjorgvin:mainfrom
tsisar:feature/waveshare-lcd-147

Conversation

@tsisar

@tsisar tsisar commented Aug 6, 2026

Copy link
Copy Markdown

Waveshare ESP32-S3-Touch-LCD-1.47 port

Adds firmware/src/boards/waveshare_lcd_147/ + [env:waveshare_lcd_147].
This is the first landscape port: the 172×320 JD9853 panel is driven as a
320×172 landscape canvas, and compute_layout() gains a landscape branch
(W > H && H < 200) that places the two usage panels side by side instead of
stacked.

Hardware notes

  • Display: JD9853 on plain 4-wire SPI (not QSPI), driven by Arduino_GFX's
    Arduino_ST7789 (shared command set) plus the vendor register init sequence
    pushed after gfx->begin() — without it the panel stays dark. Constructed
    portrait with col_offset1 = 34, then setRotation(1).
  • Backlight: the panel has no brightness command — LEDC PWM on LCD_BL.
  • Touch: AXS5106L @ I2C 0x63, small vendored inline reader (14-byte burst
    from reg 0x01). Needs a long reset pulse (200 ms low / 300 ms settle).
  • Battery: no PMU — VBAT via a 3.0× divider on GPIO12 (ADC2; uncontended
    since the firmware never starts Wi-Fi). Charging/VBUS state is unknowable,
    reported as false.
  • Buttons: the kit ships only BOOT + RESET, so BOOT takes the PWR role
    (cycle screens / brightness / hold-3s-to-pair) and BoardCaps.button_count
    is 0 — the HID Space / Shift+Tab paths never fire. No hold-to-power-off:
    there is no power-hold latch, and GPIO0 is the S3 boot strapping pin.
  • Pin map taken from the official schematic, not the wiki — Waveshare's
    own ESP-IDF BSP header has TP_RST/TP_INT swapped relative to the board.
  • No IMU, audio, or IO expander populated.

Verified on hardware: display, touch, battery ADC, BLE pairing + live
daemon data.

tsisar and others added 3 commits August 6, 2026 09:28
Seventh board port, and the first one driven in landscape: a 172x320
JD9853 IPS panel on plain 4-wire SPI, rotated to a 320x172 canvas.

The JD9853 shares enough of the ST7789 command set that Arduino_GFX's
Arduino_ST7789 drives the framebuffer path, but only after the vendor
power/gamma register sequence is pushed (jd9853_reg_init(), taken from
Waveshare's own Arduino demo) — without it the panel stays dark. The
panel is constructed portrait with col_offset1 = 34 (its 172-wide active
area starts at column 34 of the controller's GRAM) and then rotated, so
Arduino_TFT::setRotation maps the offset onto the right axis.

Touch is a vendored inline AXS5106L reader (14-byte burst from reg 0x01),
keeping the dependency tree copyleft-free like the other ports. Battery
is a 3.0x divider on GPIO12 (ADC2, uncontended since we never start
Wi-Fi); there is no PMU, IMU, IO expander or audio path on this kit.

The kit ships only BOOT and RESET, so BOOT takes the PWR role (screens /
brightness / hold-3s-release pairing) — without it the device could never
be paired at all. BoardCaps.button_count is therefore 0 and the HID
Space / Shift+Tab paths never fire here. There is deliberately no
hold-to-power-off either: no power-hold latch exists to drop, and GPIO 0
is the S3's boot strapping pin, so an ext0 LOW-level wake would sample it
while still held and drop the chip into USB download mode.

Pin map comes from the official schematic rather than the wiki, which
publishes none — note that Waveshare's own ESP-IDF BSP header has
TP_RST/TP_INT swapped relative to the board.

ui.cpp gains a landscape branch in compute_layout(): screens too short to
stack the two usage panels put them side by side instead
(usage_panels_row / usage_panel_w, with make_usage_panel generalized to
take x and w). All other ports are unaffected and still build.

Verified on hardware: display, touch controller probe, BLE advertising
and the usage / PIN / idle / splash views (captured over the screenshot
serial command). Touch coordinate handedness and the landscape direction
(rotation 1 vs 3) still want a hands-on confirmation.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@HermannBjorgvin

Copy link
Copy Markdown
Owner

Missing description, would be nice to get a short description and pictures taken of the device since I don't have one on hand.

@tsisar

tsisar commented Aug 6, 2026

Copy link
Copy Markdown
Author

My bad, fixed — description added, device photos and screenshots attached.

20260806_182724 20260806_182648 usage_lcd147

@tsisar

tsisar commented Aug 6, 2026

Copy link
Copy Markdown
Author

@HermannBjorgvin

Copy link
Copy Markdown
Owner

Looks cool!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds a new Waveshare ESP32-S3-Touch-LCD-1.47 (JD9853) board port and updates the shared UI layout logic to properly support short landscape displays by rendering the two usage panels side-by-side.

Changes:

  • Added firmware/src/boards/waveshare_lcd_147/ implementing the HAL for JD9853 SPI display, AXS5106L touch, ADC battery, and stubbed IMU/sound/input.
  • Added a landscape-strip branch to compute_layout() and updated the usage screen panel construction to support side-by-side layout.
  • Registered the new board in documentation and PlatformIO ([env:waveshare_lcd_147]), plus README/CLAUDE.md updates.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
README.md Adds the LCD-1.47 board to the supported boards list.
firmware/src/ui.cpp Introduces landscape layout support and side-by-side usage panels.
firmware/src/boards/waveshare_lcd_147/board.h Defines LCD-1.47 pin map, geometry, and capability flags.
firmware/src/boards/waveshare_lcd_147/board_init.cpp Initializes I2C bus for the touch controller.
firmware/src/boards/waveshare_lcd_147/caps.cpp Exposes BoardCaps (320×172 landscape, 0 HID buttons, battery).
firmware/src/boards/waveshare_lcd_147/display.cpp Implements JD9853-on-SPI display init (vendor reg sequence) + PWM backlight.
firmware/src/boards/waveshare_lcd_147/touch.cpp Implements minimal AXS5106L I2C touch reader + rotation mapping.
firmware/src/boards/waveshare_lcd_147/power.cpp Implements ADC-based battery % and BOOT-as-PWR edge synthesis (no PMU).
firmware/src/boards/waveshare_lcd_147/input.cpp Stubs HID buttons (BOOT reserved for PWR role).
firmware/src/boards/waveshare_lcd_147/imu.cpp Stubs IMU (not populated on this kit).
firmware/src/boards/waveshare_lcd_147/sound.cpp Stubs sound (no audio path on this kit).
firmware/platformio.ini Adds [env:waveshare_lcd_147] build configuration and deps.
docs/porting/adding-a-board.md Updates porting guide to acknowledge SPI TFTs and landscape rotation.
CLAUDE.md Adds the LCD-1.47 board to the project’s board/architecture documentation.
.gitignore Ignores /.idea/.

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

Comment thread firmware/src/boards/waveshare_lcd_147/board.h Outdated
No power-off on this board. Suggestion looks good to commit.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
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