feat(boards): add M5Stack Cardputer ADV and LilyGO T-Echo Lite KeyShield

New M5Stack Cardputer ADV variant (ESP32-S3, ST7789 TFT, built-in TCA8418
QWERTY keyboard, PI4IOE5V6408 LoRa-cap IO-expander autodetect), and a
KeyShield accessory variant for the existing LilyGO T-Echo Lite (external
TCA8418 T9 keypad + AW21009 backlight driver). Both keyboards share one
ENV_USE_TCA8418 polling block in UITask.cpp::loop(), coexisting with the
unrelated CardKB support (different chip/address/flag).

Fixes carried in from the contributed T-Echo Lite code: swapped GPS RX/TX
pins, TX-LED hooks, TCXO voltage, missing GxEPD2_122_T61 panel include.
Fixed during integration: I2C bus was probed for an RTC before Wire.begin()
configured its pins on Cardputer ADV (silent RTC autodetect failure).

Added dedicated *_solo_dual release envs for both boards (auto-picked up by
the solo-firmware release workflow). Gave the T-Echo Lite KeyShield solo
build -Os/-Ofast-unflag like every other nRF52 solo build (was missing,
cut flash usage from 90.7% to 61.4%).

Ported the shared misc-fixed 6x9 font (full Latin/Greek/Cyrillic, opt-in via
OLED_MISC_FIXED_FONT) to ST7789Display for the Cardputer's on-screen
keyboard. ST7789Spi isn't Adafruit_GFX-based like the other single-font
drivers, and this panel's logical->physical scale is non-integer, so glyphs
are re-packed to XBM and blitted through the existing drawXbm(), which
already does correct fractional-scale boundary math, rather than
duplicating that logic.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-08-08 01:06:24 +02:00
co-authored by Claude Opus 5
parent 6fd1c4bae2
commit 05e57357d3
15 changed files with 1061 additions and 5 deletions
@@ -2332,6 +2332,29 @@ void UITask::loop() {
}
#endif
pollCardKB();
#ifdef ENV_USE_TCA8418
{
extern char tca8418_keypad_read(); // provided by the active variant
char k = tca8418_keypad_read();
if (k) {
switch (k) {
case KEY_UP: enqueueKey(checkDisplayOn(KEY_UP)); break;
case KEY_ENTER: enqueueKey(checkDisplayOn(KEY_ENTER)); break;
case KEY_DOWN: enqueueKey(checkDisplayOn(KEY_DOWN)); break;
case KEY_CANCEL:enqueueKey(checkDisplayOn(KEY_CANCEL));break;
case KEY_HOME:
#ifdef LILYGO_TECHO_LITE_KEYSHIELD
extern void techo_keyshield_backlight_toggle();
techo_keyshield_backlight_toggle();
#endif
break;
default:
enqueueKey(checkDisplayOn(k));
break;
}
}
}
#endif
#if defined(BACKLIGHT_BTN)
if ((int32_t)(millis() - next_backlight_btn_check) >= 0) {
bool touch_state = digitalRead(PIN_BUTTON2);