You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 /channels2 holds only configured channels instead of always writing ~2.7 KB; and findChannelIdx() 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 ^/v glyphs 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_assert fails the build if TrailStore::CAPACITY ever outgrows the uint16_t save-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 RadioPresetPicker and RadioParamsEditor (plus nearestBwIndex() in RadioPresets.h) replace ~6 duplicated methods and several state fields per screen.
Mesh Dispatcher gains generic per-payload-type RX/TX counters and pool-free / queue-length getters; a new DeviceDiag helper reports nRF52 heap (linker-symbol + sbrk) and stack (FreeRTOS high-water-mark) headroom.
build.sh tolerates control characters in pio project config's JSON dump.