Solo's `_solo_dual` env for each board lived inside variants/<board>/, mixed in with the shared upstream board configs (repeater, room server, plain companion) that every MeshCore fork carries. Split them out into their own top-level solo/<board>/ folder -- each still `extends` the board base defined in its original variants/<board>/platformio.ini, just no longer interleaved with it file-wise. - platformio.ini: extra_configs picks up solo/*/platformio.ini alongside variants/*/platformio.ini. - build-solo-firmwares.yml: env-discovery grep now scans solo/ instead of variants/ (the release matrix is unchanged -- same 8 envs, same names). - pr-build-check.yml: solo/** added to the trigger paths. - GAT562 30S Mesh Kit: dropped the separate solo_ble env -- solo_dual is a strict superset (BLE still works, plus USB), and every other board only ever had one solo build to begin with. - GAT562 Mesh Watch13: renamed solo_ble -> solo_dual (added DUAL_SERIAL=1) to match. No comment anywhere recorded whether this board's USB data lines are actually broken out to a connector -- DUAL_SERIAL compiles and works over BLE regardless, so worst case the USB half goes unused. - Removed a dead AUTO_SHUTDOWN_MILLIVOLTS from the three solo envs that set it (Heltec V3/V4, T-Echo Lite+KeyShield): that macro is only ever read in the old ui-tiny UITask, never ui-new, which every solo build (these included) uses -- it did nothing on any of them. Left alone everywhere else it's set (non-solo companion envs elsewhere use ui-tiny/ui-orig, or the flag is legitimately read); out of scope here. - Added docs/solo_features/build_flags.md: every optional -D flag a solo build understands (GPIO, CardKB/joystick, Hall-sensor cover lock, buzzer/ vibration, GPS switch, display/battery tuning), verified against the code rather than the existing per-board comments, with what's already baked into every solo build kept separate from what's opt-in. - README: doc index + Building from source section link to the new page; path references to the moved solo files updated to solo/<board>/. All 8 solo_dual envs rebuilt clean after the move; native test suite (40 cases) unaffected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
6.2 KiB
External Keyboard & Joystick
Two optional, auto-detected hardware add-ons — a build with them enabled runs the same with nothing plugged in. Two of the newer boards also ship with their own built-in keypad instead — see Built-in keyboards.
- CardKB — an M5Stack I2C QWERTY keyboard (address
0x5F), for typing messages, names and labels without walking the on-screen letter grid. - Wired joystick — four direction contacts plus a Back button, replacing the single-button navigation on boards that have no joystick of their own.
Support by device
| Device | CardKB | Wired joystick |
|---|---|---|
| Seeed Wio Tracker L1 (OLED) | ✅ Grove connector | onboard |
| Seeed Wio Tracker L1 (E-ink) | ✅ Grove connector | onboard |
| GAT562 30S Mesh Kit | — | onboard |
| Heltec V3 (experimental) | ✅ solder to free GPIOs | ✅ solder to free GPIOs |
| Heltec V4 (experimental) | ✅ solder to free GPIOs | ✅ solder to free GPIOs |
| M5Stack Cardputer ADV (experimental) | — | built-in keyboard instead, see below |
| LilyGO T-Echo Lite + KeyShield (experimental) | — | built-in keypad instead, see below |
CardKB
Plug it into the second I2C bus (the Grove connector on the Wio Tracker L1; see Wiring for the Heltec boards). The firmware probes for it once at boot — nothing to enable in Settings.
The same bus is scanned for environment sensors, so a CardKB and a sensor can share it.
Typing
Printable characters insert straight at the cursor, bypassing the on-screen grid completely. The alphabet and T9/ABC settings do not apply — a real keyboard sends the right character already, so typing is always plain Latin ASCII regardless of what Settings › Keyboard is set to.
| Key | Action |
|---|---|
| letters / digits / symbols / space | insert at the cursor |
| Backspace | delete the character before the cursor |
| Esc | cancel / back |
| Arrows | same as the joystick |
| Enter | same as the centre button |
| Fn+Enter | submit the field — no need to find the DONE cell |
| Fn+letter | open the accent popup for that letter (e.g. Fn+A → á à ä ã…) |
| Tab | the Hold-Enter equivalent, everywhere — context menus, shift-lock, clear-all |
| Fn+Esc | lock / unlock the device (single press, works in both directions) |
Fn+Esc rather than the adjacent Fn+Backspace on purpose: Fn and Backspace sit next to each other on CardKB's layout and would be far too easy to hit by accident. See Screen Lock for the physical button equivalent.
Ext. KB — Full vs Compact
Settings › Keyboard › Ext. KB picks how the on-screen keyboard behaves while a CardKB is doing the typing.
| Mode | Behaviour |
|---|---|
| Full (default) | The letter grid stays on screen. Arrows and Enter drive the grid exactly as physical buttons do, so CardKB and the joystick can be used interchangeably. |
| Compact | The grid, the special-row icons and the status line are all hidden — only the text being typed and two shortcut hints remain. Arrows move the text cursor directly, and plain Enter submits the field (same as Fn+Enter). |
Compact is designed to need no joystick at all — the right choice when CardKB is the only input device, e.g. a Heltec V3/V4 with no joystick soldered on.
Cursor mode and the accent / placeholder popups draw their own visible feedback, so they behave identically in both modes.
Wired joystick
Four direction contacts plus a fifth "press" contact. Each contact simply shorts its pin to ground — the firmware enables the internal pull-ups, so no external resistors are needed.
- The stick's own press contact drives the centre / Enter press — your thumb is already on the stick, so pressing it in is the natural "confirm" action.
- The board's existing user button (PRG on the Heltec boards) becomes Back instead. Back is not optional: the UI uses it unconditionally once the joystick is enabled. Triple-clicking Back toggles the buzzer.
- Settings › Display › Joystick rotation rotates the direction mapping at runtime (0–3), for a stick mounted sideways in a custom enclosure. It is independent of display rotation.
Wiring (Heltec V3 / V4)
Neither board ships with a joystick or a keyboard header, so both are soldered to free GPIOs. V3 and V4 are pin-compatible per Heltec's documentation and the solo builds use the same assignment for both — confirmed working on real V4 hardware; still worth checking against your own V3 module before soldering.
| Function | GPIO | Notes |
|---|---|---|
| CardKB SDA | 3 | second I2C bus (Wire1) — not the OLED's 17/18 |
| CardKB SCL | 4 | |
| Joystick UP | 23 | |
| Joystick DOWN | 6 | |
| Joystick LEFT | 47 | |
| Joystick RIGHT | 48 | |
| Joystick press — Enter | 33 | the stick's own fifth contact; required when the joystick is enabled |
| Back | 0 | the onboard PRG button — nothing to wire |
Everything above lives in the [env:Heltec_v3_companion_solo_dual] /
[env:heltec_v4_companion_solo_dual] blocks in
solo/heltec_v3/platformio.ini
and solo/heltec_v4/platformio.ini,
with comments explaining which pins are safe to reuse. To build a CardKB-only
device, comment out the joystick block and set Ext. KB to Compact.
Built-in keyboards (Cardputer ADV, T-Echo Lite + KeyShield)
Experimental — newly-added board support, not the CardKB/joystick add-ons above. Both keypads are TCA8418-based and share one polling path, entirely independent of the CardKB code — a board can have either, or neither.
- M5Stack Cardputer ADV — built-in QWERTY, no CardKB or joystick needed.
- LilyGO T-Echo Lite + KeyShield — the KeyShield add-on gives the T-Echo Lite a T9 keypad; without it the board has no usable input for the solo UI.
Neither keypad follows CardKB's exact Fn-shortcut table (Fn+Enter,
Fn+letter accent popups, Tab, Fn+Esc lock) — see each board's own
keyboard driver under variants/ and its solo platformio.ini under solo/
for its current keymap.