merge: 1.26 into main

Scope/repeater-scope filtering, magnetic Hall-sensor screen lock,
solo build configs restructured into their own solo/<board>/ folder
(one _solo_dual build per board), ProMicro + CardKB support (PR #31,
tchellow), new Build Flags reference doc, book-order fullscreen message
paging, and a confirmed "Start OTA" admin action -- plus a full
pre-merge documentation audit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-08-29 19:06:58 +02:00
co-authored by Claude Sonnet 5
35 changed files with 763 additions and 434 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
- name: List solo_dual envs
id: list-envs
run: |
envs=$(grep -rh '^\[env:' platformio.ini variants/ \
envs=$(grep -rh '^\[env:' solo/ \
| sed 's/\[env://;s/\]//' \
| grep '_solo_dual$' \
| jq -R -s -c 'split("\n") | map(select(length > 0))')
+2
View File
@@ -7,6 +7,7 @@ on:
- 'src/**'
- 'examples/**'
- 'variants/**'
- 'solo/**'
- 'platformio.ini'
- '.github/workflows/pr-build-check.yml'
push:
@@ -15,6 +16,7 @@ on:
- 'src/**'
- 'examples/**'
- 'variants/**'
- 'solo/**'
- 'platformio.ini'
- '.github/workflows/pr-build-check.yml'
+14 -2
View File
@@ -15,16 +15,18 @@ Solo firmware thread: https://discord.com/channels/1495203904898728149/150529433
| Seeed Wio Tracker L1 (OLED) | nRF52840 | SSD1306 / SH1106 128 × 64 | `solo-<version>-WioTrackerL1.uf2` |
| Seeed Wio Tracker L1 (E-ink) | nRF52840 | GxEPD2 250 × 122 | `solo-<version>-WioTrackerL1Eink.uf2` |
| GAT562 30S Mesh Kit | nRF52840 | SSD1306 128 × 64 | `solo-<version>-GAT562-30S-Mesh-Kit.uf2` |
| GAT562 Mesh Watch13 *(experimental)* | nRF52840 | SSD1306 128 × 64 | `solo-<version>-GAT562-Mesh-Watch13.uf2` |
| Heltec LoRa32 V3 *(experimental)* | ESP32-S3 | SSD1306 128 × 64 | `solo-<version>-Heltec-v3-merged.bin` |
| Heltec LoRa32 V4 *(experimental)* | ESP32-S3 | SSD1306 128 × 64 | `solo-<version>-heltec-v4-merged.bin` |
| M5Stack Cardputer ADV *(experimental)* | ESP32-S3 | ST7789 TFT 240 × 135 | `solo-<version>-M5Stack-Cardputer-ADV-merged.bin` |
| LilyGO T-Echo Lite + KeyShield *(experimental)* | nRF52840 | GxEPD2 250 × 122 | `solo-<version>-LilyGo-T-Echo-Lite-keyshield.uf2` |
| ProMicro *(experimental)* | nRF52840 | SSD1306 128 × 64 | `solo-<version>-ProMicro.uf2` |
All firmware files are published on the [releases page](https://github.com/MarekZegare4/MeshCore-Solo/releases). Each binary supports both BLE and USB serial — there are no separate BLE/USB builds.
The MCU column decides how you flash: nRF52840 boards take a drag-and-drop `.uf2`, ESP32-S3 boards take a `.bin` written with a flasher — see [Flashing](#flashing).
The Wio Tracker L1s, GAT562 and Cardputer ADV work out of the box (the Cardputer has a built-in QWERTY keyboard). Heltec V3/V4 need [a keyboard or joystick wired up](#hardware-setup--heltec-v3--v4) first. The T-Echo Lite needs the KeyShield add-on (its own T9 keypad) to be usable standalone — see [External Keyboard & Joystick](./docs/solo_features/external_keyboard.md).
The Wio Tracker L1s, both GAT562 boards and Cardputer ADV work out of the box (the Cardputer has a built-in QWERTY keyboard). Heltec V3/V4 need [a keyboard or joystick wired up](#hardware-setup--heltec-v3--v4) first. The T-Echo Lite needs the KeyShield add-on (its own T9 keypad) to be usable standalone. ProMicro has no onboard buttons at all — a CardKB is required, sharing the board's primary I2C bus — see [External Keyboard & Joystick](./docs/solo_features/external_keyboard.md).
<!-- **Enclosures (Wio Tracker L1)**
- [E-ink case](https://www.printables.com/model/1420534-seeed-wio-tracker-l1-e-ink-enclosure)
@@ -136,7 +138,7 @@ Each joystick contact simply shorts its pin to GND — the firmware enables the
Either device is enough on its own — unwired pins read as not-pressed, and a missing CardKB just isn't detected at boot. For **CardKB-only**, wire just SDA/SCL and set Settings Keyboard **Ext. KB = Compact**, which needs no joystick at all.
These are only defaults, set in the `[env:Heltec_v3_companion_solo_dual]` / `[env:heltec_v4_companion_solo_dual]` blocks in [`variants/heltec_v3/platformio.ini`](./variants/heltec_v3/platformio.ini) and [`variants/heltec_v4/platformio.ini`](./variants/heltec_v4/platformio.ini) — comments there list which GPIOs are already claimed. Full details in [External Keyboard & Joystick](./docs/solo_features/external_keyboard.md).
These are only defaults, set in the `[env:Heltec_v3_companion_solo_dual]` / `[env:heltec_v4_companion_solo_dual]` blocks in [`solo/heltec_v3/platformio.ini`](./solo/heltec_v3/platformio.ini) and [`solo/heltec_v4/platformio.ini`](./solo/heltec_v4/platformio.ini) — comments there list which GPIOs are already claimed. Full details in [External Keyboard & Joystick](./docs/solo_features/external_keyboard.md).
---
@@ -153,6 +155,7 @@ These are only defaults, set in the `[env:Heltec_v3_companion_solo_dual]` / `[en
| [Screen Lock](./docs/solo_features/screen_lock/screen_lock.md) | Lock/unlock sequence, lock screen, auto-lock |
| [Tools Screen](./docs/solo_features/tools_screen/tools_screen.md) | GPS trail & waypoints, compass, navigation, nearby nodes, ringtone editor, remote bot, auto-advert, live location sharing, locator, diagnostics, repeater, remote admin |
| [External Keyboard & Joystick](./docs/solo_features/external_keyboard.md) | CardKB shortcuts, Full vs Compact mode, wired joystick, Heltec V3/V4 wiring |
| [Build Flags](./docs/solo_features/build_flags.md) | Every optional `-D` build flag a solo build understands — GPIO, Hall sensor, buzzer/vibration, GPS switch, display/battery tuning |
| [Solo UI framework](./docs/design/solo_ui_framework.md) | **Developer guide** — the reusable building blocks (screens, lists, popups, mini-icons, geo/persistence helpers) and how to add a new feature |
| [Feature roadmap](./docs/development/roadmap.md) | **Developer notes** — planned / done / rejected features and the code-audit backlog |
@@ -204,10 +207,12 @@ git config merge.ours.driver true
| `WioTrackerL1_companion_solo_dual` | Wio Tracker L1 (OLED) |
| `WioTrackerL1Eink_companion_solo_dual` | Wio Tracker L1 (E-ink) |
| `GAT562_30S_Mesh_Kit_solo_dual` | GAT562 30S Mesh Kit |
| `GAT562_Mesh_Watch13_solo_dual` | GAT562 Mesh Watch13 *(experimental)* |
| `Heltec_v3_companion_solo_dual` | Heltec LoRa32 V3 *(experimental)* |
| `heltec_v4_companion_solo_dual` | Heltec LoRa32 V4 *(experimental)* |
| `M5Stack_Cardputer_ADV_companion_solo_dual` | M5Stack Cardputer ADV *(experimental)* |
| `LilyGo_T-Echo-Lite_keyshield_companion_solo_dual` | LilyGO T-Echo Lite + KeyShield *(experimental)* |
| `ProMicro_companion_solo_dual` | ProMicro (nRF52840) + CardKB *(experimental)* |
```sh
pio run -e <env> # build only
@@ -217,6 +222,11 @@ FIRMWARE_VERSION=v1.0.0 bash build.sh build-firmware <env> # release artifacts i
The last command runs the same path CI does: a `.uf2` + DFU `.zip` on nRF52, or an app-only `.bin` plus a `-merged.bin` on ESP32. Releases carry the `.uf2`, the `.zip` and the `-merged.bin` only.
Every environment above builds as-is with no extra hardware required. If you've
wired up something extra — CardKB, a joystick, GPIO, a magnetic cover sensor,
a buzzer — see [Build Flags](./docs/solo_features/build_flags.md) for the full
list of optional `-D` flags to add to your own `solo/<board>/platformio.ini`.
### Releasing
Pushing a `v*` tag runs [Build Solo Firmwares](./.github/workflows/build-solo-firmwares.yml), which discovers every `*_solo_dual` environment automatically, builds them all and opens a **draft** release with the artifacts attached. Write the notes from `release-notes.md` and publish it. See [RELEASE.md](./RELEASE.md) for the upstream companion/repeater/room-server tags.
@@ -228,6 +238,7 @@ Pushing a `v*` tag runs [Build Solo Firmwares](./.github/workflows/build-solo-fi
| `examples/companion_radio/ui-new/` | the solo UI — screens, widgets, `UITask` |
| `src/helpers/ui/` | display drivers, fonts, buttons, buzzer |
| `variants/<board>/` | per-board `platformio.ini`, `target.h`, `target.cpp` |
| `solo/<board>/` | that board's solo (`*_solo_dual`) environment — kept separate from `variants/` so this fork's Solo-specific additions don't mix into configs upstream/other forks also carry |
| `docs/solo_features/` | user documentation for this fork |
| `docs/design/`, `docs/development/` | developer notes and the feature roadmap |
| `tools/` | host-side helpers (screenshot, GPX export, font conversion) |
@@ -244,5 +255,6 @@ Big thanks to the people who contributed to this fork:
- [vanous](https://github.com/vanous)
- [marczykm](https://github.com/marczykm)
- [tchellow](https://github.com/tchellow)
Built on upstream [MeshCore](https://github.com/meshcore-dev/MeshCore) and its [community](https://github.com/meshcore-dev/MeshCore/graphs/contributors).
+9 -2
View File
@@ -40,12 +40,19 @@ Shutdown reason codes (stored in GPREGRET2):
| Seeed Studio XIAO nRF52840 (`xiao_nrf52`) | Yes | Yes | Yes |
| RAK4631 (`rak4631`) | Yes | Yes | Yes |
| Heltec T114 (`heltec_t114`) | Yes | Yes | Yes |
| Heltec T1 (`heltec_t1`) | Yes | Yes | Yes |
| Heltec T096 (`heltec_t096`) | Yes | Yes | Yes |
| Heltec Tower V2 (`heltec_tower_v2`) | Yes | Yes | Yes |
| GAT562 30S Mesh Kit (`gat562_30s_mesh_kit`) | Yes | Yes | Yes |
| GAT562 Mesh Watch13 | Yes | Yes | Yes |
| GAT562 Mesh Tracker Pro (`gat562_mesh_tracker_pro`) | Yes | Yes | Yes |
| GAT562 EVB Pro (`gat562_mesh_evb_pro`) | Yes | Yes | Yes |
| muzi works R1 Neo (`muziworks_r1_neo`) | Yes | Yes | Yes |
| SenseCAP Solar | Yes | Yes | Yes |
| RAK 3401 (`rak3401`) | Yes | Yes | Yes |
| Promicro nRF52840 | No | No | No |
| RAK WisMesh Tag | No | No | No |
| Heltec Mesh Solar | No | No | No |
| LilyGo T-Echo / T-Echo Lite | No | No | No |
| SenseCAP Solar | Yes | Yes | Yes |
| WIO Tracker L1 / L1 E-Ink | No | No | No |
| WIO WM1110 | No | No | No |
| Mesh Pocket | No | No | No |
+99
View File
@@ -0,0 +1,99 @@
## Build Flags
[Go back](../../README.md)
Reference for the `-D` build flags a Solo build understands beyond the
per-board defaults already set in `solo/<board>/platformio.ini`. Add any of
these to your own board's `build_flags` (in `solo/<board>/platformio.ini`) to
enable optional hardware you've wired up yourself, or to tune a default.
Everything below is a no-op when left unset — adding a flag for hardware that
isn't there costs nothing and can't brick a build; the exceptions (pin
conflicts, wrong polarity) are called out per flag.
None of this needs touching to get a board running — see the
[environment table](../../README.md#building-from-source) for the flag-free
default build for each supported board.
---
### Already part of every solo build
Set once per board in `solo/<board>/platformio.ini`, not usually touched
per-user. Listed here so the rest of this page can assume them.
| Flag | Meaning |
| --- | --- |
| `FIRMWARE_SOLO_BUILD=1` | Marks the build as Solo (full on-device UI) rather than a companion-only firmware. |
| `DUAL_SERIAL=1` | The companion app can attach over BLE *or* USB serial, whichever it finds; BLE wins if both are live. Every solo build sets this — Solo standardises on one build per board rather than splitting BLE-only / USB-only variants. |
| `MAX_CONTACTS=<n>` | Size of the contact table. Default is 32 if unset; solo builds set 350. |
| `MAX_GROUP_CHANNELS=<n>` | Size of the channel list. Required for channel support to compile in at all — not optional the way the rest of this page is. |
| `OFFLINE_QUEUE_SIZE=<n>` | How many messages queue for later delivery while the phone app is disconnected. Default 16; solo builds set 256. |
| `UI_SENSORS_PAGE=1` | Enables the on-device sensors dashboard page. |
| `BLE_PIN_CODE=<n>` | See below — not a plain fixed value in practice. |
| `DISPLAY_CLASS=<Class>` | Selects the display driver (e.g. `SSD1306Display`, `GxEPDDisplay`, `ST7789Display` — see `src/helpers/ui/` for the full set). Fixed by whatever panel the board actually has; only relevant if you're wiring on a *different* display than stock, in which case the matching driver's `.cpp` also needs adding to `build_src_filter`. |
**`BLE_PIN_CODE`** has a special case baked in: if it's left at the literal
value `123456` *and* the board has a display, pairing uses a random 6-digit
PIN generated fresh each session and shown on-device, rather than a fixed one.
Any other numeric value is used as a static PIN instead. Leaving the flag out
entirely disables the PIN prompt (BLE pairing is unauthenticated).
---
### Input hardware add-ons
Each of these assumes you're wiring something up yourself — check pins are
actually free on your board first (see the board's `variant.h` and its
existing `solo/<board>/platformio.ini` for what's already claimed).
| Flag | Adds |
| --- | --- |
| `ENV_PIN_SDA` / `ENV_PIN_SCL` | CardKB (M5Stack I2C keyboard, addr `0x5F`) on a second I2C bus (resolves to `Wire1`). Probed at boot — harmless with nothing plugged in. See [External Keyboard & Joystick](./external_keyboard.md). |
| `CARDKB_I2C=<Wire\|Wire1>` | Same CardKB support, naming the bus directly — for a board with no free pins for a second bus, set `CARDKB_I2C=Wire` to share the primary bus (already used by the display/RTC) instead of defining `ENV_PIN_SDA`/`ENV_PIN_SCL`. Takes precedence if both are somehow set. |
| `UI_HAS_JOYSTICK=1` + `UI_HAS_JOYSTICK_UPDOWN=1` (optional) + `JOYSTICK_UP` / `JOYSTICK_DOWN` / `JOYSTICK_LEFT` / `JOYSTICK_RIGHT` + `PIN_USER_BTN` + `PIN_BACK_BTN` | A wired joystick (four direction contacts + a press contact for Enter). Replaces single-button navigation entirely once enabled. See [External Keyboard & Joystick](./external_keyboard.md). |
| `PIN_GPIO1` .. `PIN_GPIO4` | Up to four general-purpose pins, each independently switchable between Off / Input / Output (GPIO1/GPIO2 also get an Analog step, if wired to an ADC-capable pin) from Tools GPIO, and via the `!gpio1`..`!gpio4` bot commands. Not restricted to any particular board — works anywhere the pins are actually free. See [Tools Screen GPIO](./tools_screen/tools_screen.md#gpio). |
| `PIN_HALL_SENSOR` + `HALL_ACTIVE_HIGH=1` (optional) | A Hall-effect or reed sensor for a magnetic flip cover: closing locks and blanks the screen instantly, opening unlocks and wakes it, no combo either way. `HALL_ACTIVE_HIGH` is only for a module wired to pull the pin high (rather than low) when the magnet is near. See [Screen Lock Magnetic cover](./screen_lock/screen_lock.md#magnetic-cover-hall-sensor). |
| `PIN_GPS_SWITCH` | A physical on/off switch for GPS power, read alongside the software GPS toggle — the Tools screen shows `gps off(hw)` / `gps off(sw)` when the two disagree, instead of silently trusting one over the other. |
---
### Output / feedback hardware
| Flag | Adds |
| --- | --- |
| `PIN_BUZZER` (+ `PIN_BUZZER_EN`, optional) | A passive piezo buzzer, driven by direct PWM (nRF52) or the `NonBlockingRtttl` library (everything else) for RTTTL ringtones and UI beeps. `PIN_BUZZER_EN` is an optional enable line some boards wire separately from the signal pin. |
| `PIN_VIBRATION` | A vibration motor for haptic notification, via `GenericVibration`. |
---
### GPS
| Flag | Meaning |
| --- | --- |
| `ENV_INCLUDE_GPS=1` | Compiles in GPS support (NMEA parsing, location provider) at all. |
| `GPS_BAUD_RATE=<n>` | Baud rate for the GPS module's serial link (`Serial1`). Match your module's default. |
`PIN_GPS_SWITCH` (above) is independent of both — it's a hardware kill switch
layered on top of GPS support, not a requirement for it.
---
### Display & battery tuning
| Flag | Meaning |
| --- | --- |
| `OLED_MISC_FIXED_FONT=1` | Pulls in a full Latin/Greek/Cyrillic 6×9 fixed font (~14 KB flash) so typed text in those alphabets renders as itself instead of block placeholders. Worth it on any board with a keyboard; skip it on space-constrained builds without one. |
| `DISPLAY_ROTATION=<0-3>` | Rotates the panel in 90° steps, for a board mounted sideways or upside down. |
| `ENABLE_SCREENSHOT` | Lets Solo Tools read the framebuffer over USB to capture a screenshot. |
| `KEEP_DISPLAY_ON_USB` | Refreshes the auto-off deadline continuously while externally (USB) powered, so the auto-off timer only starts counting once power is actually removed. Off by default because OLED panels burn in quickly with a permanently-lit screen — only worth enabling for an LCD/e-ink target, or a display you don't mind replacing. |
| `AUTO_OFF_MILLIS=<ms>` | How long the display stays on before auto-off. Default 15000 (15s); `0` disables auto-off entirely. |
| `UI_RECENT_LIST_SIZE=<n>` | How many entries the recent-activity lists show before scrolling. Default 4. |
---
### Misc
| Flag | Meaning |
| --- | --- |
| `ADVERT_NAME='"name"'` | Sets the default node name baked into a fresh device, instead of the hex of the first 4 bytes of its public key. Note the doubled quoting — it's a C string literal passed through a build flag. |
| `MESHCORE_VERSION='"x.y"'` | Overrides the upstream MeshCore base-version string shown in diagnostics, for boards whose port hasn't been rebased onto the latest yet. Cosmetic only — doesn't change protocol behaviour. |
+10 -3
View File
@@ -23,6 +23,7 @@ see [Built-in keyboards](#built-in-keyboards-cardputer-adv-t-echo-lite--keyshiel
| 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 |
| ProMicro (nRF52840) *(experimental)* | ✅ shares the primary I2C bus (D8/D7) — no free pins for a second bus | — |
---
@@ -35,6 +36,11 @@ 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.
On a board with no free pins for a second bus (ProMicro), CardKB instead
shares the primary bus already used by the display/RTC — set `CARDKB_I2C=Wire`
as a build flag rather than `ENV_PIN_SDA`/`ENV_PIN_SCL`. See
[Build Flags](./build_flags.md) for both forms.
### Typing
Printable characters insert straight at the cursor, bypassing the on-screen grid
@@ -115,8 +121,8 @@ hardware**; still worth checking against your own V3 module before soldering.
Everything above lives in the `[env:Heltec_v3_companion_solo_dual]` /
`[env:heltec_v4_companion_solo_dual]` blocks in
[`variants/heltec_v3/platformio.ini`](../../variants/heltec_v3/platformio.ini)
and [`variants/heltec_v4/platformio.ini`](../../variants/heltec_v4/platformio.ini),
[`solo/heltec_v3/platformio.ini`](../../solo/heltec_v3/platformio.ini)
and [`solo/heltec_v4/platformio.ini`](../../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.
@@ -134,4 +140,5 @@ independent of the CardKB code — a board can have either, or neither.
Neither keypad follows CardKB's exact Fn-shortcut table (Fn+Enter,
Fn+letter accent popups, Tab, Fn+Esc lock) — see each board's own
`platformio.ini` / keyboard driver under `variants/` for its current keymap.
keyboard driver under `variants/` and its solo `platformio.ini` under `solo/`
for its current keymap.
@@ -74,7 +74,7 @@ Messages appear as chat bubbles sized to their content — **right**-anchored fo
| :-----------------------: | :-----------------------: |
| ![](./fullscreen_oled.png) | ![](./fullscreen_eink.png) |
Navigate between messages with **LEFT** (newer) and **RIGHT** (older). Long messages scroll with **UP/DOWN**.
Navigate between messages like pages in a book — **LEFT** goes back to the older message, **RIGHT** forward to the newer one. The `<` / `>` markers along the bottom edge show which directions still have a message. Long messages scroll with **UP/DOWN**.
If the message is a reply addressed to someone (`@[nick]`), a **To: nick** bar is shown below the sender name and the body is displayed without the address prefix.
@@ -51,3 +51,14 @@ The display turns off again automatically after 5 seconds of inactivity (or 2 se
### Auto-lock
Enable **Auto-lock** in **Settings Display** to lock the device automatically whenever the display turns off due to auto-off timeout.
---
### Magnetic cover (Hall sensor)
Optional, user-supplied hardware — no board in this repo has one built in. Wire a Hall-effect or reed sensor to any free GPIO, then set `PIN_HALL_SENSOR` (and `HALL_ACTIVE_HIGH=1`, if your module pulls the pin high rather than low when the magnet is present) as `build_flags` in your own env. No-op entirely unless `PIN_HALL_SENSOR` is defined.
Fully autonomous, independent of Auto-lock and of any key combo:
- **Magnet near (cover closed)** — locks and blanks the display immediately, no wake grace.
- **Magnet away (cover opened)** — unlocks and wakes the display right away.
@@ -104,6 +104,7 @@ The **repeater** mode and its flood filters live on their own screen — see **T
| Layout | ABC / T9 | On-screen keyboard style. **ABC**: a-b-c…z grid, one key per letter. **T9**: phone-keypad multi-tap — each key labelled digit+letters (e.g. `2abc`); repeated **Enter** cycles the letters then the digit. Applies to whichever script page is active, not just Latin. |
| Main | Latin / Cyrillic / Greek | Which script the keyboard opens on by default. **Latin** is the default; picking **Cyrillic** or **Greek** makes that the one you land on, with Latin moving to the Additional cycle instead. |
| Additional | Latin / Cyrillic / Greek | The second script in the **#@/abc** key's cycle (Main → Additional → Symbols → Main). Setting it to the same script as Main drops the cycle to just that script plus Symbols. **Greek** covers the 24-letter alphabet plus final sigma (`ς`), not the tonos stress accents. Every script renders natively via one shared Unicode font — no separate toggle needed. |
| Ext. KB | Full / Compact | Only shown on a build with CardKB support (`CARDKB_I2C` or `ENV_PIN_SDA`/`ENV_PIN_SCL` set). Picks how the on-screen keyboard behaves while a CardKB is doing the typing — see [External Keyboard & Joystick](../external_keyboard.md#ext-kb--full-vs-compact). |
Applies to every on-screen text field (messages, waypoint labels, room passwords, preset names). Earlier releases labelled the grid *QWERTY*; the layout has always been alphabetical, so it is now named **ABC**.
@@ -568,13 +568,13 @@ Send commands to a **repeater/room server you have admin permission on** — the
| **System** | Name, Owner info, Admin password |
| **Radio** | Frequency, Bandwidth, Spreading factor, Coding rate, TX power |
| **Routing** | Repeat, Advert interval, Flood advert interval, Max hops |
| **Actions** | Send advert, Send zero-hop advert, Sync clock, Reboot, **Custom command...** |
| **Actions** | Send advert, Send zero-hop advert, Sync clock, Reboot, Start OTA, **Custom command...** |
**Enter** on a row does one of four things, depending on the field:
- **Name / Owner info** first **fetch** the node's current value, then open the keyboard **pre-filled** with it to edit — submitting sends the change. If the fetch fails or times out, the keyboard still opens (blank), so the value can be set blind.
- **Radio and Routing rows** are typed, not free text: **Repeat** is an ON/OFF toggle; **Advert interval / Flood advert interval / Max hops / TX power** are number steppers (**LEFT/RIGHT** to adjust, within that field's valid range); **Frequency** uses the same digit-by-digit cursor editor as Settings' own Radio screen (**LEFT/RIGHT** moves between digits, **UP/DOWN** changes the selected one); **Bandwidth / Spreading factor / Coding rate** step through their valid discrete LoRa values with **LEFT/RIGHT**. All four Radio-tuple fields (Frequency/Bandwidth/SF/Coding rate) fetch and re-send the same underlying `radio` value together — editing any one of them still only overwrites that one, the other three round-trip unchanged. **Enter** sends the change; **Cancel** discards it and returns to the row list without sending anything.
- **Admin password** has no fetch (there's no way to read a password back) — it opens straight to a blank keyboard.
- **Actions** (Reboot, Send advert, …) send immediately, no editing step.
- **Actions** (Reboot, Send advert, …) send immediately, no editing step — except **Start OTA**, which asks **Start / Cancel** first (defaulting to Cancel): it puts the remote into BLE DFU mode for the duration of the update, far more disruptive than a quick reboot.
- **Custom command...** (last row of Actions) opens the same free-text entry for anything not covered above — up to 160 characters, see the linked reference for the full grammar. The keyboard's **{}** key doubles as command completion here: it lists commands matching whatever's typed since the last space (narrowing as you type), and picking one completes that word instead of just inserting after it.
4. **Read the reply** — the text reply opens in a scrollable view (**UP/DOWN** to scroll, **Cancel/Enter** to go back to the category tabs).
@@ -25,6 +25,7 @@
#include "FullscreenMsgView.h"
#include "TabBar.h"
#include "PopupMenu.h" // "Start OTA" confirmation
#include "RadioParamsEditor.h" // DigitEditor + stepSF/stepBW/stepCR -- same widgets Settings/Repeater use locally
#include <helpers/ClientACL.h> // PERM_ACL_ADMIN / PERM_ACL_ROLE_MASK
@@ -137,6 +138,15 @@ class AdminScreen : public UIScreen {
FullscreenMsgView _reply_view;
char _reply_text[200] = "";
// "Start OTA" confirmation -- pulls the remote out of the mesh into BLE DFU
// mode for the duration of the update, far more disruptive than the other
// one-shot actions on this tab, so unlike Reboot it doesn't fire on a bare
// Enter. Only this one action needs a confirm today, so it's special-cased
// in activateField() by command string rather than adding a generic
// needs_confirm flag to every AdminField literal below.
PopupMenu _confirm;
const AdminField* _pending_confirm_field = nullptr;
KeyboardWidget& kb() { return _task->keyboard(); }
bool isAdminOk(const uint8_t* pub_key) const {
@@ -226,6 +236,14 @@ class AdminScreen : public UIScreen {
if (f.get_cmd == nullptr && f.set_prefix == nullptr) { // Custom command...
openValueKb(_cmd_text, true);
} else if (f.set_prefix == nullptr) { // Action
if (!strcmp(f.get_cmd, "start ota")) { // see _confirm's comment
_pending_confirm_field = &f;
_confirm.begin("Start OTA update?", 2);
_confirm.addItem("Start");
_confirm.addItem("Cancel");
_confirm.setSelected(1); // default highlight = Cancel
return;
}
strncpy(_cmd_text, f.get_cmd, sizeof(_cmd_text) - 1);
_cmd_text[sizeof(_cmd_text) - 1] = '\0';
sendCommand();
@@ -333,6 +351,8 @@ public:
_value_editing = false;
_login_waiting = false;
_admin_ok = false;
_confirm.active = false;
_pending_confirm_field = nullptr;
}
// Canonical entry for a specific target -- called by UITask::openAdminFor(),
@@ -519,6 +539,7 @@ public:
}
}
});
if (_confirm.active) { _confirm.render(display); return 50; }
return _value_editing ? 50 : 2000;
}
@@ -552,6 +573,20 @@ public:
}
if (_phase == COMMAND) {
if (_confirm.active) {
auto res = _confirm.handleInput(c);
if (res == PopupMenu::SELECTED) {
if (_confirm.selectedIndex() == 0 && _pending_confirm_field) {
strncpy(_cmd_text, _pending_confirm_field->get_cmd, sizeof(_cmd_text) - 1);
_cmd_text[sizeof(_cmd_text) - 1] = '\0';
sendCommand();
}
_pending_confirm_field = nullptr;
} else if (res == PopupMenu::CANCELLED) {
_pending_confirm_field = nullptr;
}
return true;
}
if (_kb_active) {
auto r = kb().handleInput(c);
if (r == KeyboardWidget::DONE) {
@@ -670,6 +705,7 @@ const AdminScreen::AdminField AdminScreen::ACTION_FIELDS[] = {
{ "Send zero-hop advert", "advert.zerohop", nullptr },
{ "Sync clock", "clock sync", nullptr },
{ "Reboot", "reboot", nullptr }, // disruptive + no confirm: keep off the default row
{ "Start OTA", "start ota", nullptr }, // confirmed first -- see _confirm's comment
{ "Custom command...", nullptr, nullptr },
};
@@ -157,12 +157,14 @@ struct FullscreenMsgView {
display.print(s_wrap_lines[scroll + i]);
}
drawScrollIndicator(display, startY, visible * lineH, lcount, visible, scroll);
// Page markers read like a book: the older message is back to the left,
// the newer one forward to the right (see handleInput).
const int nav_y = display.height() - lineH;
if (has_next) {
if (has_prev) {
display.setCursor(0, nav_y);
display.print("<");
}
if (has_prev) {
if (has_next) {
display.setCursor(display.width() - cw, nav_y);
display.print(">");
}
@@ -172,8 +174,12 @@ struct FullscreenMsgView {
Result handleInput(char c) {
if (c == KEY_UP) { if (scroll > 0) scroll--; return NONE; }
if (c == KEY_DOWN) { if (scroll < _max_scroll) scroll++; return NONE; }
if (keyIsPrev(c)) return NEXT; // page between messages (encoder too)
if (keyIsNext(c)) return PREV;
// Page between messages (encoder too), in reading order: left goes back to
// the older message, right forward to the newer one. PREV/NEXT are named in
// message order, and MessagesScreen's _hist_sel counts newest-first, so PREV
// (older) is what a left press means.
if (keyIsPrev(c)) return PREV;
if (keyIsNext(c)) return NEXT;
if (c == KEY_CONTEXT_MENU) return REPLY;
if (c == KEY_ENTER || c == KEY_CANCEL) return CLOSE;
return NONE;
@@ -77,7 +77,7 @@ class SettingsScreen : public UIScreen {
KEYBOARD_TYPE,
KEYBOARD_MAIN_ALPHABET,
KEYBOARD_ALPHABET,
#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL)
#if defined(CARDKB_I2C)
KEYBOARD_CARDKB_COMPACT,
#endif
// Contacts section
@@ -611,7 +611,7 @@ class SettingsScreen : public UIScreen {
display.print("Additional");
display.setCursor(valCol(display), y);
display.print(NodePrefs::keyboardAlphabetLabel(p ? p->keyboard_alt_alphabet : 0));
#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL)
#if defined(CARDKB_I2C)
} else if (item == KEYBOARD_CARDKB_COMPACT) {
display.print("Ext. KB");
display.setCursor(valCol(display), y);
@@ -1020,7 +1020,7 @@ public:
_dirty = true;
return true;
}
#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL)
#if defined(CARDKB_I2C)
if (_selected == KEYBOARD_CARDKB_COMPACT && p && (left || right || enter)) {
p->keyboard_cardkb_compact ^= 1;
_dirty = true;
+71 -12
View File
@@ -1397,11 +1397,25 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
uint32_t aoff = autoOffMillis();
_auto_off = millis() + (aoff > 0 ? aoff : AUTO_OFF_MILLIS);
#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL)
// Wire1 is already brought up by sensors.begin() (EnvironmentSensorManager),
// which runs before this -- just probe for a CardKB sitting on it.
Wire1.beginTransmission(0x5F);
_has_cardkb = (Wire1.endTransmission() == 0);
#if defined(CARDKB_I2C)
// On the ENV_PIN_SDA/SCL path, CARDKB_I2C is Wire1, already brought up by
// sensors.begin() (EnvironmentSensorManager), which runs before this. On
// boards that set CARDKB_I2C=Wire directly in platformio.ini, that bus is
// brought up by the board's own begin() instead -- also before this.
// Either way, just probe for a CardKB sitting on it.
CARDKB_I2C.beginTransmission(0x5F);
_has_cardkb = (CARDKB_I2C.endTransmission() == 0);
#endif
#if defined(PIN_HALL_SENSOR)
// Internal pull matches the default polarity: pulled up so an active-low
// sensor reads HIGH at rest, pulled down so an active-high one reads LOW at
// rest. Most reed/Hall breakouts are open-drain, active-low -- HALL_ACTIVE_HIGH
// is only for modules wired the other way.
pinMode(PIN_HALL_SENSOR, HALL_ACTIVE_HIGH ? INPUT_PULLDOWN : INPUT_PULLUP);
_hall_magnet_present = HALL_ACTIVE_HIGH ? (digitalRead(PIN_HALL_SENSOR) == HIGH)
: (digitalRead(PIN_HALL_SENSOR) == LOW);
if (_hall_magnet_present) _locked = true; // booting with the cover already closed
#endif
#if defined(PIN_USER_BTN)
@@ -2104,7 +2118,7 @@ bool UITask::dequeueKey(char& c) {
return true;
}
#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL)
#if defined(CARDKB_I2C)
// CardKB's "fn" column (key_map in M5Stack's unit_CardKB.cpp): Fn+<physical
// key> sends 0x80 + that key's row index, entirely disjoint from every other
// code this UI recognises. Indexed by (raw - 0x80); non-letter slots (digits,
@@ -2117,7 +2131,7 @@ static const char CARDKB_FN_BASE[48] = {
};
#endif
// Poll an optional CardKB (I2C keyboard, addr 0x5F) on Wire1/Grove, feeding
// Poll an optional CardKB (I2C keyboard, addr 0x5F) on CARDKB_I2C, feeding
// the same key queue as every physical button. Most of its output needs no
// translation at all: CardKB's own arrow/Enter/Esc byte codes are already
// identical to this UI's KEY_LEFT/UP/DOWN/RIGHT/ENTER/CANCEL (0xB4-0xB7, 13,
@@ -2145,7 +2159,7 @@ static const char CARDKB_FN_BASE[48] = {
// once), so _cardkb_last_raw debounces it into one press per physical
// keypress, same as a MomentaryButton's CLICK event.
void UITask::pollCardKB() {
#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL)
#if defined(CARDKB_I2C)
if (!_has_cardkb) return;
// No artificial throttle: unlike a MomentaryButton (BUTTON_USE_INTERRUPTS
// latches every edge in an ISR ring buffer, so it survives a blocking e-ink
@@ -2156,9 +2170,9 @@ void UITask::pollCardKB() {
// Polling every loop() iteration (same as a digital button's check(), which
// has no throttle either) just shrinks that miss window down to exactly the
// render() duration instead of render()+30ms.
Wire1.requestFrom(0x5F, 1);
if (!Wire1.available()) return;
uint8_t raw = Wire1.read();
CARDKB_I2C.requestFrom(0x5F, 1);
if (!CARDKB_I2C.available()) return;
uint8_t raw = CARDKB_I2C.read();
if (raw == _cardkb_last_raw) return; // still held (or still released) -- no new edge
_cardkb_last_raw = raw;
if (raw == 0) return; // key just released, nothing to enqueue
@@ -2237,6 +2251,50 @@ void UITask::pollCardKB() {
#endif
}
// Level-triggered, like pollCardKB() -- a magnet held near the sensor reads the
// same way every tick, so this only acts on the two edges (closed/opened), not
// on every poll. Fully autonomous: closing locks and blanks the display
// immediately (no wake grace -- the cover is physically over the screen, so
// there's nothing to show), opening unlocks and wakes it, with no combo or
// keypress either way. Independent of Auto-lock (Settings > Display), which is
// a timeout-driven setting -- this is a direct physical event.
//
// Debounced against a mechanical reed switch chattering for a few ms as the
// magnet crosses the trigger distance -- a raw flip only becomes the new
// _hall_magnet_present once it's been steady for HALL_DEBOUNCE_MS, so a bounce
// can't fire the lock/unlock actions (each including a full display
// off/on -- slow and disruptive on e-ink) more than once per real transition.
void UITask::pollHallSensor() {
#if defined(PIN_HALL_SENSOR)
bool raw = HALL_ACTIVE_HIGH ? (digitalRead(PIN_HALL_SENSOR) == HIGH)
: (digitalRead(PIN_HALL_SENSOR) == LOW);
if (raw != _hall_candidate) {
_hall_candidate = raw;
_hall_candidate_since = millis();
}
if (_hall_candidate == _hall_magnet_present) return; // no debounced change yet
if (millis() - _hall_candidate_since < HALL_DEBOUNCE_MS) return; // not steady long enough
bool present = _hall_candidate;
_hall_magnet_present = present;
if (present) { // cover closed
_locked = true;
_lock_wake_until = 0;
if (_display) _display->turnOff();
#ifdef PIN_LED
digitalWrite(PIN_LED, LOW); // same as the auto-off path -- one less thing lit under a closed cover
#endif
} else { // cover opened
_locked = false;
if (_display && !_display->isOn()) _display->turnOn();
uint32_t aoff = autoOffMillis();
if (aoff > 0) _auto_off = millis() + aoff;
}
_next_refresh = 0;
#endif
}
void UITask::loop() {
// Background delivery: resend pending on-device DMs whose ACK timed out, and
// finalise the ✗ marker — runs regardless of which screen is active.
@@ -2335,6 +2393,7 @@ void UITask::loop() {
}
#endif
pollCardKB();
pollHallSensor();
#ifdef ENV_USE_TCA8418
{
extern char tca8418_keypad_read(); // provided by the active variant
@@ -2480,7 +2539,7 @@ void UITask::loop() {
}
// Hint popup at bottom (like alert style)
_display->setTextSize(1);
#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL)
#if defined(CARDKB_I2C)
const char* hint = _lock_seq_count == 0 ? (_has_cardkb ? "Back+3xEnter/Fn+Esc" : "Hold Back + 3xEnter") :
_lock_seq_count == 1 ? "Enter x2 more..." : "Enter x1 more...";
#else
+39 -6
View File
@@ -23,6 +23,21 @@
#include "../AbstractUITask.h"
#include "../NodePrefs.h"
#include "../Trail.h"
// Optional M5Stack CardKB (I2C keyboard, addr 0x5F). CARDKB_I2C names which
// TwoWire it lives on -- set at file scope (not inside the class body, and
// not resolved via an #elif ladder) so both this header and SettingsScreen.h
// see a fully-resolved macro no matter which one gets included first.
// - Boards with a free second I2C bus define ENV_PIN_SDA/ENV_PIN_SCL
// (already brought up for EnvironmentSensorManager) and get Wire1 here,
// same as before.
// - Boards without a free second bus set -D CARDKB_I2C=Wire directly in
// platformio.ini, sharing whatever bus the display/RTC already use.
// Either way it's a no-op on boards that define neither, or when nothing
// ACKs 0x5F at boot.
#if !defined(CARDKB_I2C) && defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL)
#define CARDKB_I2C Wire1
#endif
#include "../Waypoint.h"
#include "../LiveTrack.h"
#include "KeyboardWidget.h"
@@ -193,12 +208,9 @@ class UITask : public AbstractUITask {
void enqueueKey(char c);
bool dequeueKey(char& c);
// Optional M5Stack CardKB (I2C keyboard, addr 0x5F) on the Grove/Wire1 bus
// -- reuses ENV_PIN_SDA/ENV_PIN_SCL (already brought up for
// EnvironmentSensorManager) as the "this board has a second I2C bus" gate,
// rather than a new board-specific pin define. No-op entirely on boards
// without that bus, or when nothing ACKs 0x5F at boot.
#if defined(ENV_PIN_SDA) && defined(ENV_PIN_SCL)
// Optional M5Stack CardKB (I2C keyboard, addr 0x5F). See the CARDKB_I2C
// definition near the top of this file for which bus it's on and why.
#if defined(CARDKB_I2C)
bool _has_cardkb = false;
// CardKB is level-triggered, not edge-triggered -- it keeps returning the
// same byte for as long as the physical key is held, not just once. Track
@@ -208,6 +220,27 @@ class UITask : public AbstractUITask {
#endif
void pollCardKB();
// Optional magnetic "flip cover" lock: a Hall-effect or reed sensor wired to
// any free GPIO, closing (pulling active) when a magnet is near. Entirely
// user-supplied -- no board in this repo ships one, so PIN_HALL_SENSOR must
// be added as a build_flag by whoever wires the sensor up; no-op everywhere
// else. HALL_ACTIVE_HIGH overrides the default polarity for modules that
// pull the pin HIGH (instead of LOW) when the magnet is present.
#if defined(PIN_HALL_SENSOR)
#ifndef HALL_ACTIVE_HIGH
#define HALL_ACTIVE_HIGH 0
#endif
bool _hall_magnet_present = false;
// Contact-bounce guard for a mechanical reed switch (a Hall-effect IC reads
// clean, but the docs recommend either): a raw reading only replaces
// _hall_magnet_present once it's held steady for HALL_DEBOUNCE_MS, same
// threshold and reasoning as MomentaryButton's ISR_DEBOUNCE_MS.
static const uint32_t HALL_DEBOUNCE_MS = 25;
bool _hall_candidate = false;
uint32_t _hall_candidate_since = 0;
#endif
void pollHallSensor();
void setCurrScreen(UIScreen* c);
// Centred alert overlay (the showAlert() box). Wraps long text to up to
+1
View File
@@ -11,6 +11,7 @@
[platformio]
extra_configs =
variants/*/platformio.ini
solo/*/platformio.ini
platformio.local.ini
[arduino_base]
+5
View File
@@ -3,9 +3,14 @@
### What's new
- **On-device community scope, and repeater-side scope filtering.** Settings Radio gets a **Scope** field — type a region/community name (e.g. `pl`) and every device typing the same name derives the same shared tag, no key exchange needed; it's what your own DM/channel sends carry, previously only settable from a connected app. Tools Repeater gains **Scope only** (only relay flood traffic matching your own scope, or one of the new **Extra scopes** below — a no-op until a scope is actually set, so it can't silently blackhole all forwarding) and **Extra scopes** (comma-separated additional regions to relay for, without changing what scope this device's own messages send under).
- **Optional magnetic "flip cover" screen lock**, for anyone who wants to wire a Hall-effect or reed sensor to a free GPIO — no board ships one built in. Set `PIN_HALL_SENSOR` as a build flag on your own env and closing the cover locks and blanks the screen instantly, opening it unlocks and wakes it — no combo, independent of Auto-lock. See [Screen Lock](docs/solo_features/screen_lock/screen_lock.md#magnetic-cover-hall-sensor).
- **Experimental: solo build for ProMicro (nRF52840)**, with CardKB support sharing the board's primary I2C bus (no free pins for a second one on this board). Contributed by @tchellow — thanks!
- **New [Build Flags](docs/solo_features/build_flags.md) reference** — every optional `-D` flag a solo build understands (GPIO, CardKB/joystick, Hall-sensor cover lock, buzzer/vibration, GPS switch, display/battery tuning) in one place.
- **Tools Admin gains a "Start OTA" action** for a repeater/room server you're logged into — sends the same `start ota` CLI command the Custom-command row already reached, now with its own menu row and a confirm ("Start" defaulting to "Cancel" first) since it puts the remote into BLE DFU mode for the duration of the update.
### Fixes
- **Paging through the fullscreen message view now reads like a book****RIGHT** moves forward to the newer message, **LEFT** back to the older one, and the `<` / `>` markers along the bottom edge follow suit. It was the other way round before.
- **Hardware CAD and RSSI interference-threshold detection were silently hardcoded off on companion_radio**, regardless of any setting. CAD now auto-enables whenever RX power-save (duty-cycle) is active — the noise floor isn't kept fresh during duty-cycle sleep, so a fresh hardware channel scan before TX is needed instead of the RSSI-threshold check.
- **A long message could split a multi-byte UTF-8 character in half when truncated to fit the send frame** (e.g. a Polish/accented character landing right at the cut-off), delivering a mangled trailing byte to the app. Truncation now stops at the last complete character.
- **Deleting the default "Public" channel didn't stick — it came back on every reboot.** A deleted channel is correctly left out of the saved channel file (to avoid rewriting it every save), but the Public channel was unconditionally re-added at every boot *before* the saved list was loaded, so its absence from the file never got a chance to matter. Now only seeded on a genuinely fresh device (no channel file yet) — once you've saved any channel state at all, your own list is authoritative.
+52
View File
@@ -0,0 +1,52 @@
; Solo build for GAT562 30S Mesh Kit -- extends the board base defined in
; variants/gat562_30s_mesh_kit/platformio.ini. Solo configs live in their own
; top-level solo/ folder, separate from the shared upstream board variants in
; variants/, so this repo's Solo-specific additions don't get mixed in with
; configs other MeshCore forks/upstream also carry.
;
; Dual (BLE+USB) only -- the previous BLE-only solo_ble env was dropped since
; dual is a strict superset (BLE still works, plus USB) and Solo standardises
; on one build per board.
[env:GAT562_30S_Mesh_Kit_solo_dual]
extends = GAT562_30S_Mesh_Kit
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
; Optimise for size, not speed: the nRF52 Arduino core defaults to -Ofast
; (≈ -O3 + -ffast-math), which bloats flash by ~200 KB on this feature-rich
; solo build. -Os keeps every feature, fits comfortably, and is actually safer
; for float (no fast-math reassociation). Speed is irrelevant for the UI/mesh.
build_unflags = -Ofast
build_flags =
${GAT562_30S_Mesh_Kit.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D MESHCORE_VERSION='"1.17"'
-D UI_SENSORS_PAGE=1
-D UI_HAS_JOYSTICK_UPDOWN=1
-D ADVERT_NAME='"@@MAC"'
-D ENV_INCLUDE_GPS=1
; misc-fixed 6x9 OLED font (full Latin/Greek/Cyrillic), same as the Wio L1
; builds. Solo only: it costs ~14 KB of flash and the repeater/companion
; builds have no keyboard to type those alphabets on.
-D OLED_MISC_FIXED_FONT=1
-D DUAL_SERIAL=1
-D ENABLE_SCREENSHOT
-Os
; QSPIFLASH disabled: QSPI IO0/IO2 pins (P0.30/P0.28) conflict with joystick LEFT/UP
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_30S_Mesh_Kit.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/buzzer.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${GAT562_30S_Mesh_Kit.lib_deps}
adafruit/RTClib @ ^2.1.3
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
+50
View File
@@ -0,0 +1,50 @@
; Solo build for GAT562 Mesh Watch13 -- extends the board base defined in
; variants/gat562_mesh_watch13/platformio.ini. Solo configs live in their own
; top-level solo/ folder, separate from the shared upstream board variants in
; variants/, so this repo's Solo-specific additions don't get mixed in with
; configs other MeshCore forks/upstream also carry.
;
; Renamed from the previous BLE-only solo_ble to solo_dual (DUAL_SERIAL added
; below) to match every other board's single solo build. This board has no
; comment anywhere recording whether its USB data lines are actually broken
; out to a connector (only charging pins might be) -- DUAL_SERIAL compiles
; and works over BLE regardless, so worst case the USB half just goes unused.
[env:GAT562_Mesh_Watch13_solo_dual]
extends = GAT562_Mesh_Watch13
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
build_flags =
${GAT562_Mesh_Watch13.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256
-D DUAL_SERIAL=1
-D FIRMWARE_SOLO_BUILD=1
-D MESHCORE_VERSION='"1.17"'
-D UI_SENSORS_PAGE=1
-D ADVERT_NAME='"@@MAC"'
; GPS — re-enable (base undefines it); Serial1 pins 15/16 from variant
-D ENV_INCLUDE_GPS=1
-D GPS_BAUD_RATE=9600
; Buzzer available on IO3 (pin 21) — uncomment to enable
; -D PIN_BUZZER=21
; -D PIN_VIBRATION=36
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_Mesh_Watch13.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/GenericVibration.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
; If PIN_BUZZER is enabled above, also add:
; +<helpers/ui/buzzer.cpp>
lib_deps =
${GAT562_Mesh_Watch13.lib_deps}
adafruit/RTClib @ ^2.1.3
densaugeo/base64 @ ~1.4.0
; If PIN_BUZZER is enabled, also add:
; end2endzone/NonBlockingRTTTL@^1.3.0
+89
View File
@@ -0,0 +1,89 @@
; Solo build for Heltec LoRa32 V3 -- extends the board base defined in
; variants/heltec_v3/platformio.ini. Solo configs live in their own top-level
; solo/ folder, separate from the shared upstream board variants in variants/,
; so this repo's Solo-specific additions don't get mixed in with configs
; other MeshCore forks/upstream also carry.
;
; Solo build: the full standalone on-device UI (message history, contacts, map,
; tools) rather than a screen that only mirrors the phone app. Dual transport --
; the companion app can attach over BLE or USB serial, whichever it finds, and
; BLE wins while both are live.
;
; This firmware needs a real input device: the solo UI cannot be driven from the
; PRG button alone. Both supported ones are wired up in target.cpp and enabled
; below, so either is enough on its own and having both is fine. The pins are
; defaults picked from what this board leaves free -- change them to match how
; the device is actually built. Pins with nothing attached read as not-pressed,
; so the unused half costs nothing.
;
; * CardKB (M5Stack I2C keyboard, addr 0x5F) on a second I2C bus. Any two free
; GPIOs -- NOT 17/18, the OLED already owns those on Wire. It's probed at
; boot, so a build with these set still runs fine with nothing plugged in.
; Pair it with Settings > Keyboard > Ext. KB = Compact, which is designed to
; need no joystick at all. The same bus is scanned for environment sensors.
;
; * Wired joystick: four direction pins plus a fifth "press" contact. The
; press contact drives Enter (your thumb's already on the stick) via
; PIN_USER_BTN -- overridden below (a later -D wins, no -U needed: this whole
; project builds with -w) from the PRG-button default
; the base env sets, since PRG's GPIO0 can't be moved to the stick. PRG
; becomes Back instead (PIN_BACK_BTN), so it no longer needs its own
; separately-wired button. Each contact just shorts its pin to GND;
; target.cpp enables the internal pull-ups. Drop
; UI_HAS_JOYSTICK_UPDOWN for a left/right-only stick. JOYSTICK_ROTATION (0-3)
; rotates the mapping if the stick is mounted sideways -- it's also a runtime
; setting, so leave it out unless you want a different default.
; Comment the whole block out for a CardKB-only build. UI_HAS_JOYSTICK
; replaces the single-button handling rather than adding to it (UITask.cpp
; dispatches on '#if UI_HAS_JOYSTICK ... #elif defined(PIN_USER_BTN)'), which
; costs nothing here -- that fallback only feeds KEY_NEXT/KEY_PREV, which the
; solo screens don't act on.
;
; V3 and V4 are pin-compatible per Heltec's own docs, so the defaults below are
; carried over from the heltec_v4_companion_solo_dual env, where this exact
; CardKB + joystick combination is confirmed working on real hardware -- still
; worth checking against your own V3 module before soldering, but not a blind
; guess like the earlier SDA 41/SCL 42 default was. PIN_GPS_RX=47/TX=48/EN=26
; above are dead defines on V3 (ENV_INCLUDE_GPS is never set to 1 in this file),
; so they don't conflict with reusing 47/48 here despite the name.
[env:Heltec_v3_companion_solo_dual]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SSD1306Display
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D DUAL_SERIAL=1 ; companion app over BLE *or* USB serial
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D UI_SENSORS_PAGE=1
-D OLED_MISC_FIXED_FONT=1 ; full Latin/Greek/Cyrillic 6x9 font, ~14 KB flash
-D ENABLE_SCREENSHOT ; same as the other solo builds — Solo Tools reads the framebuffer over USB
; CardKB on the second I2C bus. Harmless with nothing plugged in.
-D ENV_PIN_SDA=3
-D ENV_PIN_SCL=4
; Wired joystick — comment the block out for a CardKB-only build. The
; press contact (Enter) overrides PIN_USER_BTN from its PRG default;
; PRG becomes Back (PIN_BACK_BTN) instead.
-D UI_HAS_JOYSTICK=1
-D UI_HAS_JOYSTICK_UPDOWN=1
-D JOYSTICK_UP=23
-D JOYSTICK_DOWN=6
-D JOYSTICK_LEFT=47
-D JOYSTICK_RIGHT=48
-D PIN_BACK_BTN=0 ; PRG button
-D PIN_USER_BTN=33 ; joystick press contact -- Enter, overrides the PRG default above
; -D PIN_BUZZER=<gpio>
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/buzzer.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
+96
View File
@@ -0,0 +1,96 @@
; Solo build for Heltec LoRa32 V4 -- extends the board base defined in
; variants/heltec_v4/platformio.ini. Solo configs live in their own top-level
; solo/ folder, separate from the shared upstream board variants in variants/,
; so this repo's Solo-specific additions don't get mixed in with configs
; other MeshCore forks/upstream also carry.
;
; Solo build: the full standalone on-device UI (message history, contacts, map,
; tools) rather than a screen that only mirrors the phone app. Dual transport --
; the companion app can attach over BLE or USB serial, whichever it finds, and
; BLE wins while both are live. OLED board only -- the TFT variant would need
; its own DISPLAY_CLASS.
;
; This firmware needs a real input device: the solo UI cannot be driven from the
; PRG button alone. Both supported ones are wired up in target.cpp and enabled
; below, so either is enough on its own and having both is fine. The pins are
; defaults picked from what this board leaves free -- change them to match how
; the device is actually built. Pins with nothing attached read as not-pressed,
; so the unused half costs nothing.
;
; * CardKB (M5Stack I2C keyboard, addr 0x5F) on a second I2C bus. Any two free
; GPIOs -- NOT 17/18, the OLED already owns those on Wire. It's probed at
; boot, so a build with these set still runs fine with nothing plugged in.
; Pair it with Settings > Keyboard > Ext. KB = Compact, which is designed to
; need no joystick at all. The same bus is scanned for environment sensors.
; Defaults below: SDA 3, SCL 4 -- the pins heltec_v4_sensor and
; heltec_v4_expansionkit_repeater already use for their second I2C bus, i.e.
; the expansion kit's. (Those envs disagree on the order: two say SDA 3 /
; SCL 4, one says the reverse. 3/4 is the pair either way; swap them if the
; keyboard doesn't answer.)
;
; * Wired joystick: four direction pins plus a fifth "press" contact. The
; press contact drives Enter (your thumb's already on the stick) via
; PIN_USER_BTN -- overridden below (a later -D wins, no -U needed: this whole
; project builds with -w) from the PRG-button default
; the base env sets, since PRG's GPIO0 can't be moved to the stick. PRG
; becomes Back instead (PIN_BACK_BTN), so it no longer needs its own
; separately-wired button. Each contact just shorts its pin to GND;
; target.cpp enables the internal pull-ups. Drop
; UI_HAS_JOYSTICK_UPDOWN for a left/right-only stick. JOYSTICK_ROTATION (0-3)
; rotates the mapping if the stick is mounted sideways -- it's also a runtime
; setting, so leave it out unless you want a different default.
; Comment the whole block out for a CardKB-only build. UI_HAS_JOYSTICK
; replaces the single-button handling rather than adding to it (UITask.cpp
; dispatches on '#if UI_HAS_JOYSTICK ... #elif defined(PIN_USER_BTN)'), which
; costs nothing here -- that fallback only feeds KEY_NEXT/KEY_PREV, which the
; solo screens don't act on.
;
; Free on this board, per its pinout: 3, 4, 6, 23, 33, 43, 44, 45, 46, 47, 48.
; Two of those can't take an I2C pull-up: 45 selects VDD_SPI at boot, so held
; high the chip comes up expecting 1.8V flash and won't boot at all, and 46 is
; the boot-mode strap. 3 is a strapping pin too, but it only picks the JTAG
; source -- and it's what this board's own expansion kit uses for I2C anyway.
; 43/44 are UART0: unused by this build, since ARDUINO_USB_CDC_ON_BOOT (set in
; boards/heltec_v4.json) makes Serial the native USB port, but a USB-UART bridge
; may still be wired to them, so they're left alone.
[env:heltec_v4_companion_solo_dual]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SSD1306Display
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D DUAL_SERIAL=1 ; companion app over BLE *or* USB serial
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D UI_SENSORS_PAGE=1
-D OLED_MISC_FIXED_FONT=1 ; full Latin/Greek/Cyrillic 6x9 font, ~14 KB flash
-D ENABLE_SCREENSHOT ; same as the other solo builds — Solo Tools reads the framebuffer over USB
; CardKB on the second I2C bus. Harmless with nothing plugged in.
-D ENV_PIN_SDA=3
-D ENV_PIN_SCL=4
; Wired joystick — comment the block out for a CardKB-only build. The
; press contact (Enter) overrides PIN_USER_BTN from its PRG default;
; PRG becomes Back (PIN_BACK_BTN) instead.
-D UI_HAS_JOYSTICK=1
-D UI_HAS_JOYSTICK_UPDOWN=1
-D JOYSTICK_UP=23
-D JOYSTICK_DOWN=6
-D JOYSTICK_LEFT=47
-D JOYSTICK_RIGHT=48
-D PIN_BACK_BTN=0 ; PRG button
-D PIN_USER_BTN=33 ; joystick press contact -- Enter, overrides the PRG default above
; -D PIN_BUZZER=<gpio>
build_src_filter = ${heltec_v4_oled.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/buzzer.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${heltec_v4_oled.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
+43
View File
@@ -0,0 +1,43 @@
; Solo build for LilyGO T-Echo Lite + KeyShield -- extends the board base
; defined in variants/lilygo_techo_lite/platformio.ini. Solo configs live in
; their own top-level solo/ folder, separate from the shared upstream board
; variants in variants/, so this repo's Solo-specific additions don't get
; mixed in with configs other MeshCore forks/upstream also carry.
;
[env:LilyGo_T-Echo-Lite_keyshield_companion_solo_dual]
extends = LilyGo_T-Echo-Lite
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
; Optimise for size, not speed: the nRF52 Arduino core defaults to -Ofast
; (≈ -O3 + -ffast-math), which bloats flash by ~200 KB on this feature-rich
; solo build. -Os keeps every feature, fits comfortably, and is actually safer
; for float (no fast-math reassociation). Speed is irrelevant for the UI/mesh.
build_unflags = -Ofast
build_flags =
${LilyGo_T-Echo-Lite.build_flags}
-I src/helpers/ui
-I examples/companion_radio/ui-new
-D LILYGO_TECHO_LITE_KEYSHIELD
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; -D QSPIFLASH=1
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
-D UI_RECENT_LIST_SIZE=9
-D UI_SENSORS_PAGE=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D ENV_USE_TCA8418=1
-D FIRMWARE_SOLO_BUILD=1
-D MESHCORE_VERSION='"1.17"'
-D ENABLE_SCREENSHOT
-Os
build_src_filter = ${LilyGo_T-Echo-Lite.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${LilyGo_T-Echo-Lite.lib_deps}
densaugeo/base64 @ ~1.4.0
;https://github.com/lewisxhe/SensorLib.git
+34
View File
@@ -0,0 +1,34 @@
; Solo build for M5Stack Cardputer ADV -- extends the board base defined in
; variants/m5stack_cardputer_adv/platformio.ini. Solo configs live in their own
; top-level solo/ folder, separate from the shared upstream board variants in
; variants/, so this repo's Solo-specific additions don't get mixed in with
; configs other MeshCore forks/upstream also carry.
;
[env:M5Stack_Cardputer_ADV_companion_solo_dual]
extends = M5Stack_Cardputer_ADV
build_flags =
${M5Stack_Cardputer_ADV.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D DUAL_SERIAL=1
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D MESHCORE_VERSION='"1.17"'
-D UI_SENSORS_PAGE=1
; misc-fixed 6x9 font (full Latin/Greek/Cyrillic), same as the Wio L1/Heltec
; solo builds. Solo only: it costs ~14 KB of flash, and this board's own
; QWERTY keyboard is exactly the case that benefits from typing those
; alphabets and having them render as themselves instead of blocks.
-D OLED_MISC_FIXED_FONT=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${M5Stack_Cardputer_ADV.build_src_filter}
+<helpers/esp32/*.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${M5Stack_Cardputer_ADV.lib_deps}
densaugeo/base64 @ ~1.4.0
+45
View File
@@ -0,0 +1,45 @@
; Solo build for ProMicro (nRF52840) -- extends the board base defined in
; variants/promicro/platformio.ini. Solo configs live in their own top-level
; solo/ folder, separate from the shared upstream board variants in variants/,
; so this repo's Solo-specific additions don't get mixed in with configs
; other MeshCore forks/upstream also carry.
;
; Full on-device UI, with CardKB support: CardKB shares the board's primary
; I2C bus (already used by the OLED display / RTC) instead of a dedicated
; second bus -- the default Wire1 pins on this variant (D13/D14) physically
; collide with the LoRa SPI bus (P_LORA_NSS=13, P_LORA_MOSI=14), and no other
; free GPIO pair is broken out on this board for a second dedicated bus. Do
; NOT define ENV_PIN_SDA/ENV_PIN_SCL here -- that would bring up a real Wire1
; on the colliding pins instead.
[env:ProMicro_companion_solo_dual]
extends = Promicro
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
; -Ofast (the core's default) doesn't fit a feature-complete solo build;
; -Os fits with headroom.
build_unflags = -Ofast
build_flags = ${Promicro.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D DUAL_SERIAL=1
-D OFFLINE_QUEUE_SIZE=256
-D DISPLAY_CLASS=SSD1306Display
-D FIRMWARE_SOLO_BUILD=1
-D UI_SENSORS_PAGE=1
-D ENABLE_SCREENSHOT
-Os
; CardKB on the shared primary bus (D8=SDA / D7=SCL on this board).
-D CARDKB_I2C=Wire
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Promicro.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps = ${Promicro.lib_deps}
adafruit/RTClib @ ^2.1.3
densaugeo/base64 @ ~1.4.0
+19
View File
@@ -0,0 +1,19 @@
; Solo build for Seeed Wio Tracker L1 (E-ink) -- extends WioTrackerL1Eink,
; defined in variants/wio-tracker-l1-eink/platformio.ini. Solo configs live in
; their own top-level solo/ folder, separate from the shared upstream board
; variants in variants/, so this repo's Solo-specific additions don't get
; mixed in with configs other MeshCore forks/upstream also carry.
;
; Dual BLE+USB with added Solo
[env:WioTrackerL1Eink_companion_solo_dual]
extends = WioTrackerL1Eink
; Optimise for size, not speed: the nRF52 Arduino core defaults to -Ofast
; (≈ -O3 + -ffast-math), which bloats flash by ~200 KB on this feature-rich
; solo build. -Os keeps every feature, fits comfortably, and is actually safer
; for float (no fast-math reassociation). Speed is irrelevant for the UI/mesh.
build_unflags = -Ofast
build_flags = ${WioTrackerL1Eink.build_flags}
-D DUAL_SERIAL=1
-D ENABLE_SCREENSHOT
-Os
extra_scripts = post:create-uf2.py
+19
View File
@@ -0,0 +1,19 @@
; Solo build for Seeed Wio Tracker L1 (OLED) -- extends WioTrackerL1CompanionDual,
; defined in variants/wio-tracker-l1/platformio.ini. Solo configs live in their
; own top-level solo/ folder, separate from the shared upstream board variants
; in variants/, so this repo's Solo-specific additions don't get mixed in with
; configs other MeshCore forks/upstream also carry.
;
[env:WioTrackerL1_companion_solo_dual]
extends = WioTrackerL1CompanionDual
; Optimise for size, not speed: the nRF52 Arduino core defaults to -Ofast
; (≈ -O3 + -ffast-math), which bloats flash by ~200 KB on this feature-rich
; solo build. -Os keeps every feature, fits comfortably, and is actually safer
; for float (no fast-math reassociation). Speed is irrelevant for the UI/mesh.
build_unflags = -Ofast
build_flags = ${WioTrackerL1CompanionDual.build_flags}
-D UI_HAS_JOYSTICK_UPDOWN=1
-D ENABLE_SCREENSHOT
-D DUAL_SERIAL=1
-Os
extra_scripts = post:create-uf2.py
@@ -113,91 +113,6 @@ lib_deps =
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:GAT562_30S_Mesh_Kit_solo_ble]
extends = GAT562_30S_Mesh_Kit
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
; Optimise for size, not speed: the nRF52 Arduino core defaults to -Ofast
; (≈ -O3 + -ffast-math), which bloats flash by ~200 KB on this feature-rich
; solo build. -Os keeps every feature, fits comfortably, and is actually safer
; for float (no fast-math reassociation). Speed is irrelevant for the UI/mesh.
build_unflags = -Ofast
build_flags =
${GAT562_30S_Mesh_Kit.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D MESHCORE_VERSION='"1.17"'
-D UI_SENSORS_PAGE=1
-D UI_HAS_JOYSTICK_UPDOWN=1
-D ADVERT_NAME='"@@MAC"'
-D ENV_INCLUDE_GPS=1
; misc-fixed 6x9 OLED font (full Latin/Greek/Cyrillic), same as the Wio L1
; builds. Solo only: it costs ~14 KB of flash and the repeater/companion
; builds have no keyboard to type those alphabets on.
-D OLED_MISC_FIXED_FONT=1
-Os
; QSPIFLASH disabled: QSPI IO0/IO2 pins (P0.30/P0.28) conflict with joystick LEFT/UP
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_30S_Mesh_Kit.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/buzzer.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${GAT562_30S_Mesh_Kit.lib_deps}
adafruit/RTClib @ ^2.1.3
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:GAT562_30S_Mesh_Kit_solo_dual]
extends = GAT562_30S_Mesh_Kit
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
; Optimise for size, not speed: the nRF52 Arduino core defaults to -Ofast
; (≈ -O3 + -ffast-math), which bloats flash by ~200 KB on this feature-rich
; solo build. -Os keeps every feature, fits comfortably, and is actually safer
; for float (no fast-math reassociation). Speed is irrelevant for the UI/mesh.
build_unflags = -Ofast
build_flags =
${GAT562_30S_Mesh_Kit.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D MESHCORE_VERSION='"1.17"'
-D UI_SENSORS_PAGE=1
-D UI_HAS_JOYSTICK_UPDOWN=1
-D ADVERT_NAME='"@@MAC"'
-D ENV_INCLUDE_GPS=1
; misc-fixed 6x9 OLED font (full Latin/Greek/Cyrillic), same as the Wio L1
; builds. Solo only: it costs ~14 KB of flash and the repeater/companion
; builds have no keyboard to type those alphabets on.
-D OLED_MISC_FIXED_FONT=1
-D DUAL_SERIAL=1
-D ENABLE_SCREENSHOT
-Os
; QSPIFLASH disabled: QSPI IO0/IO2 pins (P0.30/P0.28) conflict with joystick LEFT/UP
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_30S_Mesh_Kit.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/buzzer.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${GAT562_30S_Mesh_Kit.lib_deps}
adafruit/RTClib @ ^2.1.3
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:GAT562_30S_Mesh_Kit_kiss_modem]
extends = GAT562_30S_Mesh_Kit
@@ -87,45 +87,6 @@ lib_deps =
${GAT562_Mesh_Watch13.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:GAT562_Mesh_Watch13_solo_ble]
extends = GAT562_Mesh_Watch13
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
build_flags =
${GAT562_Mesh_Watch13.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=SSD1306Display
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D MESHCORE_VERSION='"1.17"'
-D UI_SENSORS_PAGE=1
-D ADVERT_NAME='"@@MAC"'
; GPS — re-enable (base undefines it); Serial1 pins 15/16 from variant
-D ENV_INCLUDE_GPS=1
-D GPS_BAUD_RATE=9600
; Buzzer available on IO3 (pin 21) — uncomment to enable
; -D PIN_BUZZER=21
; -D PIN_VIBRATION=36
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${GAT562_Mesh_Watch13.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/GenericVibration.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
; If PIN_BUZZER is enabled above, also add:
; +<helpers/ui/buzzer.cpp>
lib_deps =
${GAT562_Mesh_Watch13.lib_deps}
adafruit/RTClib @ ^2.1.3
densaugeo/base64 @ ~1.4.0
; If PIN_BUZZER is enabled, also add:
; end2endzone/NonBlockingRTTTL@^1.3.0
[env:GAT562_Mesh_Watch13_kiss_modem]
extends = GAT562_Mesh_Watch13
build_src_filter = ${GAT562_Mesh_Watch13.build_src_filter}
-85
View File
@@ -180,91 +180,6 @@ lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
; Solo build: the full standalone on-device UI (message history, contacts, map,
; tools) rather than a screen that only mirrors the phone app. Dual transport --
; the companion app can attach over BLE or USB serial, whichever it finds, and
; BLE wins while both are live.
;
; This firmware needs a real input device: the solo UI cannot be driven from the
; PRG button alone. Both supported ones are wired up in target.cpp and enabled
; below, so either is enough on its own and having both is fine. The pins are
; defaults picked from what this board leaves free -- change them to match how
; the device is actually built. Pins with nothing attached read as not-pressed,
; so the unused half costs nothing.
;
; * CardKB (M5Stack I2C keyboard, addr 0x5F) on a second I2C bus. Any two free
; GPIOs -- NOT 17/18, the OLED already owns those on Wire. It's probed at
; boot, so a build with these set still runs fine with nothing plugged in.
; Pair it with Settings > Keyboard > Ext. KB = Compact, which is designed to
; need no joystick at all. The same bus is scanned for environment sensors.
;
; * Wired joystick: four direction pins plus a fifth "press" contact. The
; press contact drives Enter (your thumb's already on the stick) via
; PIN_USER_BTN -- overridden below (a later -D wins, no -U needed: this whole
; project builds with -w) from the PRG-button default
; the base env sets, since PRG's GPIO0 can't be moved to the stick. PRG
; becomes Back instead (PIN_BACK_BTN), so it no longer needs its own
; separately-wired button. Each contact just shorts its pin to GND;
; target.cpp enables the internal pull-ups. Drop
; UI_HAS_JOYSTICK_UPDOWN for a left/right-only stick. JOYSTICK_ROTATION (0-3)
; rotates the mapping if the stick is mounted sideways -- it's also a runtime
; setting, so leave it out unless you want a different default.
; Comment the whole block out for a CardKB-only build. UI_HAS_JOYSTICK
; replaces the single-button handling rather than adding to it (UITask.cpp
; dispatches on '#if UI_HAS_JOYSTICK ... #elif defined(PIN_USER_BTN)'), which
; costs nothing here -- that fallback only feeds KEY_NEXT/KEY_PREV, which the
; solo screens don't act on.
;
; V3 and V4 are pin-compatible per Heltec's own docs, so the defaults below are
; carried over from the heltec_v4_companion_solo_dual env, where this exact
; CardKB + joystick combination is confirmed working on real hardware -- still
; worth checking against your own V3 module before soldering, but not a blind
; guess like the earlier SDA 41/SCL 42 default was. PIN_GPS_RX=47/TX=48/EN=26
; above are dead defines on V3 (ENV_INCLUDE_GPS is never set to 1 in this file),
; so they don't conflict with reusing 47/48 here despite the name.
[env:Heltec_v3_companion_solo_dual]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SSD1306Display
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D DUAL_SERIAL=1 ; companion app over BLE *or* USB serial
-D AUTO_SHUTDOWN_MILLIVOLTS=3400
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D UI_SENSORS_PAGE=1
-D OLED_MISC_FIXED_FONT=1 ; full Latin/Greek/Cyrillic 6x9 font, ~14 KB flash
-D ENABLE_SCREENSHOT ; same as the other solo builds — Solo Tools reads the framebuffer over USB
; CardKB on the second I2C bus. Harmless with nothing plugged in.
-D ENV_PIN_SDA=3
-D ENV_PIN_SCL=4
; Wired joystick — comment the block out for a CardKB-only build. The
; press contact (Enter) overrides PIN_USER_BTN from its PRG default;
; PRG becomes Back (PIN_BACK_BTN) instead.
-D UI_HAS_JOYSTICK=1
-D UI_HAS_JOYSTICK_UPDOWN=1
-D JOYSTICK_UP=23
-D JOYSTICK_DOWN=6
-D JOYSTICK_LEFT=47
-D JOYSTICK_RIGHT=48
-D PIN_BACK_BTN=0 ; PRG button
-D PIN_USER_BTN=33 ; joystick press contact -- Enter, overrides the PRG default above
; -D PIN_BUZZER=<gpio>
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/buzzer.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:Heltec_v3_companion_radio_wifi]
extends = Heltec_lora32_v3
build_flags =
-92
View File
@@ -223,98 +223,6 @@ lib_deps =
${heltec_v4_oled.lib_deps}
densaugeo/base64 @ ~1.4.0
; Solo build: the full standalone on-device UI (message history, contacts, map,
; tools) rather than a screen that only mirrors the phone app. Dual transport --
; the companion app can attach over BLE or USB serial, whichever it finds, and
; BLE wins while both are live. OLED board only -- the TFT variant would need
; its own DISPLAY_CLASS.
;
; This firmware needs a real input device: the solo UI cannot be driven from the
; PRG button alone. Both supported ones are wired up in target.cpp and enabled
; below, so either is enough on its own and having both is fine. The pins are
; defaults picked from what this board leaves free -- change them to match how
; the device is actually built. Pins with nothing attached read as not-pressed,
; so the unused half costs nothing.
;
; * CardKB (M5Stack I2C keyboard, addr 0x5F) on a second I2C bus. Any two free
; GPIOs -- NOT 17/18, the OLED already owns those on Wire. It's probed at
; boot, so a build with these set still runs fine with nothing plugged in.
; Pair it with Settings > Keyboard > Ext. KB = Compact, which is designed to
; need no joystick at all. The same bus is scanned for environment sensors.
; Defaults below: SDA 3, SCL 4 -- the pins heltec_v4_sensor and
; heltec_v4_expansionkit_repeater already use for their second I2C bus, i.e.
; the expansion kit's. (Those envs disagree on the order: two say SDA 3 /
; SCL 4, one says the reverse. 3/4 is the pair either way; swap them if the
; keyboard doesn't answer.)
;
; * Wired joystick: four direction pins plus a fifth "press" contact. The
; press contact drives Enter (your thumb's already on the stick) via
; PIN_USER_BTN -- overridden below (a later -D wins, no -U needed: this whole
; project builds with -w) from the PRG-button default
; the base env sets, since PRG's GPIO0 can't be moved to the stick. PRG
; becomes Back instead (PIN_BACK_BTN), so it no longer needs its own
; separately-wired button. Each contact just shorts its pin to GND;
; target.cpp enables the internal pull-ups. Drop
; UI_HAS_JOYSTICK_UPDOWN for a left/right-only stick. JOYSTICK_ROTATION (0-3)
; rotates the mapping if the stick is mounted sideways -- it's also a runtime
; setting, so leave it out unless you want a different default.
; Comment the whole block out for a CardKB-only build. UI_HAS_JOYSTICK
; replaces the single-button handling rather than adding to it (UITask.cpp
; dispatches on '#if UI_HAS_JOYSTICK ... #elif defined(PIN_USER_BTN)'), which
; costs nothing here -- that fallback only feeds KEY_NEXT/KEY_PREV, which the
; solo screens don't act on.
;
; Free on this board, per its pinout: 3, 4, 6, 23, 33, 43, 44, 45, 46, 47, 48.
; Two of those can't take an I2C pull-up: 45 selects VDD_SPI at boot, so held
; high the chip comes up expecting 1.8V flash and won't boot at all, and 46 is
; the boot-mode strap. 3 is a strapping pin too, but it only picks the JTAG
; source -- and it's what this board's own expansion kit uses for I2C anyway.
; 43/44 are UART0: unused by this build, since ARDUINO_USB_CDC_ON_BOOT (set in
; boards/heltec_v4.json) makes Serial the native USB port, but a USB-UART bridge
; may still be wired to them, so they're left alone.
[env:heltec_v4_companion_solo_dual]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SSD1306Display
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D DUAL_SERIAL=1 ; companion app over BLE *or* USB serial
-D AUTO_SHUTDOWN_MILLIVOLTS=3400
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D UI_SENSORS_PAGE=1
-D OLED_MISC_FIXED_FONT=1 ; full Latin/Greek/Cyrillic 6x9 font, ~14 KB flash
-D ENABLE_SCREENSHOT ; same as the other solo builds — Solo Tools reads the framebuffer over USB
; CardKB on the second I2C bus. Harmless with nothing plugged in.
-D ENV_PIN_SDA=3
-D ENV_PIN_SCL=4
; Wired joystick — comment the block out for a CardKB-only build. The
; press contact (Enter) overrides PIN_USER_BTN from its PRG default;
; PRG becomes Back (PIN_BACK_BTN) instead.
-D UI_HAS_JOYSTICK=1
-D UI_HAS_JOYSTICK_UPDOWN=1
-D JOYSTICK_UP=23
-D JOYSTICK_DOWN=6
-D JOYSTICK_LEFT=47
-D JOYSTICK_RIGHT=48
-D PIN_BACK_BTN=0 ; PRG button
-D PIN_USER_BTN=33 ; joystick press contact -- Enter, overrides the PRG default above
; -D PIN_BUZZER=<gpio>
build_src_filter = ${heltec_v4_oled.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/buzzer.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${heltec_v4_oled.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:heltec_v4_companion_radio_wifi]
extends = heltec_v4_oled
build_flags =
-39
View File
@@ -45,45 +45,6 @@ lib_deps =
debug_tool = jlink
upload_protocol = nrfutil
[env:LilyGo_T-Echo-Lite_keyshield_companion_solo_dual]
extends = LilyGo_T-Echo-Lite
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
; Optimise for size, not speed: the nRF52 Arduino core defaults to -Ofast
; (≈ -O3 + -ffast-math), which bloats flash by ~200 KB on this feature-rich
; solo build. -Os keeps every feature, fits comfortably, and is actually safer
; for float (no fast-math reassociation). Speed is irrelevant for the UI/mesh.
build_unflags = -Ofast
build_flags =
${LilyGo_T-Echo-Lite.build_flags}
-I src/helpers/ui
-I examples/companion_radio/ui-new
-D LILYGO_TECHO_LITE_KEYSHIELD
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; -D QSPIFLASH=1
-D BLE_PIN_CODE=123456
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
-D UI_RECENT_LIST_SIZE=9
-D UI_SENSORS_PAGE=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
-D AUTO_SHUTDOWN_MILLIVOLTS=3300
-D ENV_USE_TCA8418=1
-D FIRMWARE_SOLO_BUILD=1
-D MESHCORE_VERSION='"1.17"'
-D ENABLE_SCREENSHOT
-Os
build_src_filter = ${LilyGo_T-Echo-Lite.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${LilyGo_T-Echo-Lite.lib_deps}
densaugeo/base64 @ ~1.4.0
;https://github.com/lewisxhe/SensorLib.git
[env:LilyGo_T-Echo-Lite_repeater]
extends = LilyGo_T-Echo-Lite
build_src_filter = ${LilyGo_T-Echo-Lite.build_src_filter}
@@ -97,35 +97,6 @@ lib_deps =
${M5Stack_Cardputer_ADV.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:M5Stack_Cardputer_ADV_companion_solo_dual]
extends = M5Stack_Cardputer_ADV
build_flags =
${M5Stack_Cardputer_ADV.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D DUAL_SERIAL=1
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D MESHCORE_VERSION='"1.17"'
-D UI_SENSORS_PAGE=1
; misc-fixed 6x9 font (full Latin/Greek/Cyrillic), same as the Wio L1/Heltec
; solo builds. Solo only: it costs ~14 KB of flash, and this board's own
; QWERTY keyboard is exactly the case that benefits from typing those
; alphabets and having them render as themselves instead of blocks.
-D OLED_MISC_FIXED_FONT=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${M5Stack_Cardputer_ADV.build_src_filter}
+<helpers/esp32/*.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${M5Stack_Cardputer_ADV.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:M5Stack_Cardputer_ADV_repeater]
extends = M5Stack_Cardputer_ADV
build_flags =
@@ -70,20 +70,6 @@ build_flags = ${WioTrackerL1Eink.build_flags}
-D DUAL_SERIAL=1
extra_scripts = post:create-uf2.py
; Dual BLE+USB with added Solo
[env:WioTrackerL1Eink_companion_solo_dual]
extends = WioTrackerL1Eink
; Optimise for size, not speed: the nRF52 Arduino core defaults to -Ofast
; (≈ -O3 + -ffast-math), which bloats flash by ~200 KB on this feature-rich
; solo build. -Os keeps every feature, fits comfortably, and is actually safer
; for float (no fast-math reassociation). Speed is irrelevant for the UI/mesh.
build_unflags = -Ofast
build_flags = ${WioTrackerL1Eink.build_flags}
-D DUAL_SERIAL=1
-D ENABLE_SCREENSHOT
-Os
extra_scripts = post:create-uf2.py
; Dual BLE+USB with screenshot support (development/debug)
[env:WioTrackerL1Eink_companion_dual_dev]
extends = WioTrackerL1Eink
-14
View File
@@ -150,20 +150,6 @@ build_flags = ${WioTrackerL1CompanionDual.build_flags}
-D UI_HAS_JOYSTICK_UPDOWN=1
extra_scripts = post:create-uf2.py
[env:WioTrackerL1_companion_solo_dual]
extends = WioTrackerL1CompanionDual
; Optimise for size, not speed: the nRF52 Arduino core defaults to -Ofast
; (≈ -O3 + -ffast-math), which bloats flash by ~200 KB on this feature-rich
; solo build. -Os keeps every feature, fits comfortably, and is actually safer
; for float (no fast-math reassociation). Speed is irrelevant for the UI/mesh.
build_unflags = -Ofast
build_flags = ${WioTrackerL1CompanionDual.build_flags}
-D UI_HAS_JOYSTICK_UPDOWN=1
-D ENABLE_SCREENSHOT
-D DUAL_SERIAL=1
-Os
extra_scripts = post:create-uf2.py
[env:WioTrackerL1_companion_dual_dev]
extends = WioTrackerL1CompanionDual
build_flags = ${WioTrackerL1CompanionDual.build_flags}