Migrate to Waveshare ESP32-S3-Touch-AMOLED-2.16 with auto-rotation, splash, and battery

Full hardware swap from Panlee SC01 Plus (480×320 IPS) to Waveshare 2.16"
square AMOLED (480×480, CO5300 + CST9220 + AXP2101 + QMI8658). Library
stack moves to Arduino_GFX, SensorLib, XPowersLib on the pioarduino
platform 55.03.38-1 (Arduino Core 3.x).

UI:
- 4 screens (splash, usage, controller, bluetooth) with 3-button physical
  navigation: GPIO 0 = prev, AXP PKEY = cycle, GPIO 18 = next.
- IMU-driven 90° auto-rotation. CO5300 can't rotate via MADCTL, so flush
  callback does CPU strip-rotation in PARTIAL render mode. Rotation
  transitions use AMOLED brightness flash (instant black → redraw → ramp).
- Battery indicator (Lucide icons) in upper-right, RGB565A8 alpha so it
  blends over the splash animations.
- USB plugged/unplugged auto-switches between Usage and Controller
  screens (suppressed while on splash).
- Fonts and icons re-scaled ~1.9× for the higher-DPI panel; 20px margins
  to clear rounded corners.

Splash:
- 13 × 20×20 pixel-art creature animations sourced from
  claudepix.vercel.app via tools/scrape_claudepix.js (scraper handles
  both PRESET creature-engine and standalone FRAMES+PAL formats).
  tools/convert_to_c.js emits firmware/src/splash_animations.h.
  Attribution preserved in README and the generated header.

Tooling:
- tools/png_to_lvgl.js converts alpha PNGs to LVGL RGB565A8 (planar
  layout, with --tint to colorize Lucide black-on-transparent sources).
- tools/scrape_claudepix.js, tools/convert_to_c.js for the splash
  pipeline.

Docs:
- New worktree CLAUDE.md with hardware pin map, file inventory, build
  commands, and the 8 critical gotchas (CO5300 rotation, OPI PSRAM,
  pioarduino requirement, LVGL 9 font patching, centralized touch read,
  even-aligned flush regions, touch swap/mirror values, RGB565A8 layout).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Hermann Björgvin Haraldsson
2026-05-09 22:04:04 +00:00
co-authored by Claude Opus 4.7
parent 10b8052bcc
commit 97a5443601
65 changed files with 121542 additions and 801 deletions
+93
View File
@@ -0,0 +1,93 @@
[
{
"filename": "idle_breathe.html",
"name": "idle breathe",
"category": "Idle",
"frame_count": 16,
"palette_size": 3
},
{
"filename": "idle_blink.html",
"name": "idle blink",
"category": "Idle",
"frame_count": 16,
"palette_size": 3
},
{
"filename": "idle_look_around.html",
"name": "idle look around",
"category": "Idle",
"frame_count": 17,
"palette_size": 3
},
{
"filename": "expression_wink.html",
"name": "expression wink",
"category": "Expressions",
"frame_count": 12,
"palette_size": 3
},
{
"filename": "expression_surprise.html",
"name": "expression surprise",
"category": "Expressions",
"frame_count": 12,
"palette_size": 3
},
{
"filename": "expression_sleep.html",
"name": "expression sleep",
"category": "Expressions",
"frame_count": 24,
"palette_size": 3
},
{
"filename": "dance_bounce.html",
"name": "dance bounce",
"category": "Dance",
"frame_count": 16,
"palette_size": 3
},
{
"filename": "dance_sway.html",
"name": "dance sway",
"category": "Dance",
"frame_count": 12,
"palette_size": 3
},
{
"filename": "work_coding.html",
"name": "work coding",
"category": "Work",
"frame_count": 23,
"palette_size": 10
},
{
"filename": "work_think.html",
"name": "work think",
"category": "Work",
"frame_count": 24,
"palette_size": 3
},
{
"filename": "dance_bounce_dj.html",
"name": "dance bounce dj",
"category": "Dance",
"frame_count": 16,
"palette_size": 10
},
{
"filename": "dance_sway_dj.html",
"name": "dance sway dj",
"category": "Dance",
"frame_count": 12,
"palette_size": 10
},
{
"filename": "dance_djmix.html",
"name": "dance djmix",
"category": "Dance",
"frame_count": 16,
"palette_size": 10
}
]
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff