Add AMOLED-1.8 board + device-abstraction refactor for community ports#25
Merged
HermannBjorgvin merged 2 commits intoMay 21, 2026
Merged
Conversation
Owner
|
Built and works perfectly on my board. This is a really nice contribution thank you, especially the template and the instructions on adapting other boards, much appreciated! |
9 tasks
Port the firmware to a second Waveshare AMOLED board variant alongside
the original 2.16" / 480×480. Selection is at build time via a board
macro; both envs continue to build and flash independently.
Hardware delta vs AMOLED-2.16:
* Display: SH8601 QSPI (vs CO5300), 368×448 portrait (vs 480² square),
SCLK on GPIO 11 (vs 38), RST routed through an XCA9554 I/O expander
(vs direct GPIO).
* Touch: FT3168 @ 0x38 (vs CST9220 @ 0x5A). Driven by a ~30-line
inline FocalTech-protocol reader in main.cpp — Waveshare's
Arduino_DriveBus library is GPLv3 and would force the project's
license, which the README explicitly avoids.
* I/O expander: new XCA9554/PCA9554 @ I2C 0x20 gates LCD_RST, TP_RST,
audio amp enable, and the PWR button. Wrapped in io_expander.{h,cpp}.
Must initialize BEFORE display/touch or both stay in reset.
* PMU + IMU: same AXP2101 + QMI8658 as 2.16, so power.cpp/imu.cpp
largely reuse. IMU is initialized for I2C bus health but rotation
is fixed at 0° (the portrait panel doesn't benefit from auto-rotate
and the strip-rotation CPU path is excluded entirely).
* Buttons: only BOOT (GPIO 0) is a direct GPIO; PWR is read via
XCA9554 EXIO4 polling. No third button — the AMOLED-2.16's
Shift+Tab key (GPIO 18) is dropped for this board.
* Flash: 16MB (vs 8MB), partition table set to default_16MB.csv.
Code structure:
* display_cfg.h hosts a #ifdef BOARD_AMOLED_18 / #else / #endif split
with a PlatformDisplay typedef so call sites elsewhere stay clean.
* main.cpp, power.cpp, ui.cpp, splash.cpp gate board-specific bits on
the same macro. Layout constants (panel heights, content Y, font
choices on the Bluetooth screen) compress for the 368×448 portrait
footprint so two usage panels + bottom animation label fit without
horizontal overflow.
* Splash scales the 20×20 pixel-art grid to 360×360 (CELL=18 vs 24)
and centers in the portrait canvas.
* Old AMOLED-2.16 env is unchanged at the source level (gated under
#ifndef BOARD_AMOLED_18) and continues to compile + flash on the
original hardware.
CLAUDE.md updated with the two-board pin maps, build/flash commands
for both envs (macOS + Linux device paths), and the per-board gotchas.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HermannBjorgvin
approved these changes
May 21, 2026
Replaces the build-flag-driven #ifdef sprawl (~30 blocks across 6 files)
with a small HAL in firmware/src/hal/ and per-board folders under
firmware/src/boards/. Shared code (main.cpp, ui.cpp, splash.cpp) no
longer contains a single `#ifdef BOARD_*` — optional features are
guarded by BoardCaps (runtime) and BOARD_HAS_* macros (compile-time,
inside the board's own files).
Why: lets community contributors port to new ESP32 + AMOLED + touch
combos by dropping in a boards/<name>/ folder + a PlatformIO env,
without touching shared files. See docs/porting/adding-a-board.md.
Highlights:
- New HAL: display_hal, touch_hal, input_hal, power_hal, imu_hal,
board_caps. Each board provides display.cpp, touch.cpp, input.cpp,
power.cpp, imu.cpp, caps.cpp, board_init.cpp + private hardware
drivers (e.g. io_expander.{h,cpp} on AMOLED-1.8).
- PlatformIO build_src_filter selects each board's folder per env.
- ui.cpp picks fonts and layout from board_caps() via compute_layout()
with screen-height breakpoints (>= 460 → large, else compact).
- splash.cpp computes CELL = min(W,H)/20 — responsive instead of two
hardcoded values.
- idle.cpp (from HermannBjorgvin#24) rewired through display_hal + power_hal — no
longer depends on the deleted display_cfg.h / power.h.
- power_hal gains power_hal_is_vbus_in() for idle's
IDLE_SLEEP_WHEN_CHARGING gate.
- boards/template/ + docs/porting/{adding-a-board,hal-contract,
capability-flags}.md to bootstrap new ports.
- display_cfg.h, power.{h,cpp}, imu.{h,cpp}, io_expander.{h,cpp}
deleted from src/ root (moved into boards/<name>/ or hal/).
Verification: both `pio run -e waveshare_amoled_216` and
`pio run -e waveshare_amoled_18` succeed unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7d98f23 to
2035121
Compare
Contributor
Author
|
@HermannBjorgvin I am not able to merge it, can you help? thanks |
Owner
|
Yes merged and rebased the activity-stream branch |
This was referenced May 21, 2026
jjhuff
added a commit
to jjhuff/Clawdmeter
that referenced
this pull request
May 21, 2026
New port under firmware/src/boards/lilygo_t4s3/ implementing the HAL introduced by PR HermannBjorgvin#25: - RM690B0 QSPI panel with col_offset=16 (visible 450 cols inside 482-wide controller RAM), no rotation - CST226SE touch via SensorLib TouchClassCST226 - SY6970 charger PMU (XPOWERS_CHIP_SY6970); voltage→% approximation since the chip is a charger, not a fuel gauge - PMICEN (GPIO 9) raised in board_init() before display brings up, so the panel rail is alive when display_hal_init() probes the QSPI bus - No IMU, no PMU push-button, no second GPIO button — screen cycling maps to a 1500 ms long-hold of BOOT synthesized as a PWR press inside power_hal, well above a comfortable voice-mode PTT hold so it doesn't trigger accidentally ui.cpp::compute_layout() gets a narrow-panel override: the BT "Address:" line at styrene_28 clipped the right margin on the 450-wide panel, so a single-font swap to styrene_24 kicks in for c.width < 470. The two reference ports are unchanged (480 ≥ 470; 368 was already in the compact branch with styrene_20). Verified on hardware: splash, usage, and BT screens all render correctly; BLE handshakes with the host daemon and shows Connected with the MAC. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6 tasks
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
Two related changes that together make the project welcoming to new
board ports:
commit you'd already see in my fork — SH8601 + FT3168 + XCA9554,
368×448 portrait).
firmware/src/hal/+ per-board folders underfirmware/src/boards/instead of the build-flag-driven
#ifdef BOARD_*sprawl the secondport introduced. Shared code (
main.cpp,ui.cpp,splash.cpp) isnow
#ifdef-free.After this lands, adding a third board (or letting somebody else add
theirs) is
cp -r firmware/src/boards/template firmware/src/boards/<new>/,edit the TODOs, add a PlatformIO env. No shared file touches.
What changed
HAL (
firmware/src/hal/) — public interfaces shared code calls:display_hal,touch_hal,input_hal,power_hal,imu_hal,board_caps. Compile-time selection via PlatformIO'sbuild_src_filter,not virtual functions — no vtable cost.
Per-board folders (
firmware/src/boards/):waveshare_amoled_216/— CO5300 + CST9220 + AXP PKEY + QMI8658 rotationwaveshare_amoled_18/— SH8601 + FT3168 + AXP + XCA9554 (PWR via EXIO4), no rotationtemplate/— copy-this-to-start-a-port skeletonEach board owns its
board.h(pins, I2C addrs,BOARD_HAS_*flags),board_init.cpp(Wire.begin + any IO expander release),display.cpp,touch.cpp,input.cpp,power.cpp,imu.cpp,caps.cpp, plus anyboard-private hardware drivers.
Responsive UI:
ui.cpp::compute_layout()picks fonts and layoutfrom
board_caps()at runtime — current breakpointsH ≥ 460→ large,else compact.
splash.cppcomputesCELL = min(W, H) / 20instead ofthe two hardcoded values from the previous port.
Capability flags:
BoardCaps(runtime struct) for things sharedcode queries;
BOARD_HAS_*(compile-time macros) for things the linkercan dead-strip per board. See
docs/porting/capability-flags.md.Docs:
docs/porting/{adding-a-board, hal-contract, capability-flags}.md.Deleted from
src/root (moved into boards// or hal/):display_cfg.h,power.{h,cpp},imu.{h,cpp},io_expander.{h,cpp}.Stats
#ifdef BOARD_*blocks across 6 files → 0 in shared codemain.cppshrinks from ~590 lines to ~250ui.cppLayout struct replaces ~3 separate#ifdef BOARD_AMOLED_18blocks for fonts/dimensionsTest plan
pio run -d firmware -e waveshare_amoled_216succeedspio run -d firmware -e waveshare_amoled_18succeedsscreenshots/amoled_18/)Notes for review
branches in my fork. They're sequenced — once Activity merges, I'll
rebase those on top of this refactor; the refactor pattern absorbs
the Activity-screen
#ifdefs cleanly (already done in my downstream).docs/porting/hal-contract.md:contributors choose any library that fits the contract; the FT3168
vendored reader pattern is what we used to avoid GPL'ing the project.
build_src_filterensures only one board's
display.cpp/touch.cpp/etc. links intoeach env. Runtime
BoardCapsis for things UI / main loop need toquery (button count, has_battery, etc.) so shared code doesn't need
to branch on board identity at all.
🤖 Generated with Claude Code