MeshCore Solo Companion Firmware v1.20
What's new
- Repeater mode — a solo companion can now opt in to relaying mesh traffic, configured from a dedicated Tools › Repeater screen that consolidates the toggle, the forwarding filters, live forwarding stats, and a separate radio profile:
- Forwarding filters (all flood-only, off by default) — skip-advert (don't re-flood the highest-volume advert traffic), max-hops (drop a flood once it has travelled too far), yield (extra retransmit-delay so a mobile node defers to better-sited fixed repeaters), and min-SNR (don't re-flood marginal fringe packets). Plus overhear suppression, which cancels a queued retransmit if a peer relays the same packet first.
- Dedicated radio profile — an optional "Custom" Freq/SF/BW/CR used only while relaying, separate from the companion's own network and band-matched to the companion frequency by default. It's applied everywhere a radio change can happen (boot, on-device toggle, app-driven
CMD_SET_RADIO_PARAMS, Settings edits) so the device never silently relays on the wrong params. - While relaying, Adaptive Power Control is pinned to the ceiling and duty-cycle RX is forced off — a repeater needs to hear and relay at consistent power.
- Radio settings overhaul (Settings › Radio) — 16 community-suggested presets plus manual Freq/SF/BW/CR tuning (digit-by-digit frequency editor), and 4 persisted user preset slots. Presets and the manual editor are now shared between Settings and the Repeater screen — a preset saved from either place shows up in both, and you can save the current profile as a named preset or delete one from either screen.
- On-device Diagnostics (Tools › Diagnostics) — a single scrollable screen showing packet counts by category (RX/TX), radio noise floor / RSSI / SNR, packet-pool free count and outbound queue length, actually-forwarded packet count, uptime, and live heap/stack headroom, with a reset-counters popup.
Fixes
- Channel storage hardening —
saveChannels()skips unused (all-zero) slots, so/channels2holds only configured channels instead of always writing ~2.7 KB; andfindChannelIdx()rejects an all-zero secret so a corrupted/empty channel can't match an unused slot and misroute messages. - e-ink UI scaling — self-sizing popup menu scaled for landscape e-ink (no stray header gap, tighter row tiling); popup menu uses the shared proportional scroll indicator instead of raw
^/vglyphs and stops the selection bar before the scrollbar gutter; compass tape ticks/pointer and trail-map markers scale for e-ink, with wrap-around map navigation. - Joystick rotation is now persisted on e-ink builds.
- Trail capacity guard — a
static_assertfails the build ifTrailStore::CAPACITYever outgrows theuint16_tsave-header count, instead of silently truncating.
Under the hood
- Packet pool bumped 16 → 32 so queued retransmits no longer starve incoming-packet allocation while relaying.
- Shared, UITask-decoupled
RadioPresetPickerandRadioParamsEditor(plusnearestBwIndex()inRadioPresets.h) replace ~6 duplicated methods and several state fields per screen. - Mesh
Dispatchergains generic per-payload-type RX/TX counters and pool-free / queue-length getters; a newDeviceDiaghelper reports nRF52 heap (linker-symbol +sbrk) and stack (FreeRTOS high-water-mark) headroom. build.shtolerates control characters inpio project config's JSON dump.