Tidies the Trail screen end to end, with no functional change beyond the
intended UX cleanups. Squashed from refactor/trail-screen.
Popup:
- Two-level action menu (Hold Enter): short main menu (Start/Stop, Mark
here, Waypoints…, Trail file…, Settings…) plus "Trail file…" and
"Settings…" submenus, replacing one flat ~12-item list that mixed
settings and actions. One interaction pattern per level; Reset lives in
Trail file…, away from a stray Enter. Settings submenu is view-aware
(Grid only on Map, Readout only on Summary).
Map:
- MapProjection (geo→pixel) built once and shared by the map, grid and
marker drawing — removes the duplicated projection math and renderGrid's
11 scalar params.
- renderMap split into computeBounds() and drawMarkers() helpers.
Grid:
- Square cells fitted to the frame: the shorter side is divided into a
whole number of equal cells (grid touches that pair of borders), and the
longer side centres the whole cells that fit — square, symmetric, no
one-sided drift. Drawn as one dot per intersection (legible on OLED).
Waypoints:
- Extracted the whole waypoint management UI (list / navigate / add-by-
coords / mark / rename / delete / send) into a self-contained
WaypointsView component that TrailScreen owns and delegates to.
- Dropped the redundant bulk "Clear all" (per-waypoint Delete covers it).
Docs updated (tools_screen.md) + design rationale (docs/design/
trail_redesign.md). Builds clean on solo envs.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two independent, default-off toggles under Settings › Radio.
Pwr save: hardware RX duty-cycle (SX126x SetRxDutyCycle via
startReceiveDutyCycleAuto). The chip cycles RX↔sleep and wakes on a preamble —
no MCU state machine; recvRaw reads the packet exactly as in continuous RX.
Falls back to continuous RX on non-SX126x. (Replaces an earlier software-CAD
state machine that fought the hardware: polling a warm-sleeping chip gave a
phantom-busy channel that stalled TX ~4 s and dropped ACKs in the scan gaps.)
Auto pwr: Adaptive Power Control. tx_power_dbm becomes a ceiling; actual TX
power tracks the reverse-link SNR margin (measured above the per-SF demod floor,
EWMA-smoothed, proportional step with a deadband). Feedback comes from direct /
room-server ACKs and, for channels (no ACK), from hearing a repeater rebroadcast
our own flood; a lost confirmation ramps power back up so channel sends can't get
stranded below what the repeaters can hear.
Prefs schema 0xC0DE0009 (rx_powersave, tx_apc). Radio page / name bar show the
live TX power; noise floor reads n/a while duty-cycling.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Settings › Sound gains an "AD sound" row, and Auto-Advert notes the audible
"in range" heartbeat: the device chirps on every received advert (any node),
melody chosen by AD sound; there's no off, so silence it via the Buzzer
setting. built-in still chirps.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Release notes covering the navigation suite (waypoints, GPS compass,
navigate-to-point, mesh location share, waypoints in GPX), the global
metric/imperial Units setting, the long-message buffer fix, plus the
existing v1.14 items, under docs/releases/solo-v1.14.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
GPX dumps previously contained only the <trk>. Emit saved waypoints as
<wpt> elements (label → <name>, plus <time> when the RTC was set) before
the track, per GPX 1.1 ordering, in both live and saved-file exports. The
emitter is duck-typed over the waypoint store so Trail.h stays decoupled
from Waypoint.h; labels are XML-escaped. They now import as pins in OsmAnd /
Garmin / GPX Studio alongside the track.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Waypoints list header now reads "WAYPOINTS <n>/<cap>" (e.g. 3/16) so
it's clear at a glance how many waypoints are stored and how much room is
left before the table is full.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add-by-coords sat in the top-level Trail action popup alongside Mark here.
Move it into the Waypoints view as a trailing "+ Add by coords" row, so the
popup stays focused on trail/marking actions and waypoint management lives
in one place. "Waypoints" is now always shown in the action menu (it hosts
the list, backtrack and the add entry), so the first waypoint can be added
by coordinates even with no trail or saved points yet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The on-screen keyboard has no comma or minus, so a single "lat,lon" entry
was unworkable. Replace it with a WP_ADD form: separate Lat / Lon / Label
rows plus Save. Lat/Lon take a magnitude from the keyboard and a hemisphere
(N/S, E/W) toggled with LEFT/RIGHT, so negative coordinates need no minus
key. Save validates the range, auto-names a blank label, and stores the
point via the normal waypoint path.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New Trail action "Add by coords" creates a waypoint without a GPS fix: the
keyboard takes a "lat,lon" string (decimal degrees), parsed by the shared
geo::parseLatLon; on success it falls through to the normal label keyboard
(blank → auto WP<n>). Useful for a meeting point or a spot read off a map.
Invalid input reports "Bad coordinates".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
While a trail exists the map now fits the recorded route (plus the live
position) and no longer folds waypoints into the bounding box, so a far-off
waypoint can't zoom the view out and squash the trail. Waypoints that
project outside the framed area are clamped to the nearest edge (marker +
label) instead of being lost off-screen. With no trail, the view still
auto-fits to the waypoints as before.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Previously a shared location was only actionable after opening the message
fullscreen; Hold Enter on a history row only ever offered Reply. Route the
DM and channel list context menus through the same buildFsMenu /
dispatchFsAction path as the fullscreen view, so Navigate / Save waypoint
appear directly on the list row when the selected message carries a
location (Navigate returns to the list on Back).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Waypoints list → Hold Enter → Send hands the point to the Messages screen
as "[WAY]<lat>,<lon> <label>" (same text format geo::parseLatLon already
reads). The user picks a contact or channel, the text lands prefilled in
the keyboard to confirm/edit, then sends — closing the loop with the
Navigate / Save waypoint actions on the receiving end.
- QuickMsgScreen: share-compose mode (startShare/beginShareCompose). Picking
a recipient jumps straight to the prefilled keyboard; cancel returns home;
afterSend clears the mode.
- UITask::shareToMessage hands off from TrailScreen to the Messages screen.
- TrailScreen: "Send" added to the waypoint Rename/Delete popup; builds the
[WAY] payload at the {loc} precision (5 dp).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The shrunken ring left only a few-pixel needle in the OLED's short vertical
space. Switch to a linear heading tape: a fixed travel-direction pointer at
centre over a scrolling N..E..S..W scale (30° ticks, N/E/S/W labelled),
with the large degrees+cardinal readout below. The tape is purely linear
(no trig) and uses the available width, so it stays readable on the small
panel. Update the Compass docs to match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add the Settings › System "Units" (Metric/Imperial) row and update the
Trail action-menu entry from the old four-way km/h·mph·min/km·min/mi
"Units" cycle to a Speed/Pace "Readout" toggle within the global system.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Clarify in both the Map view row and the Waypoints section that the
current GPS position and all waypoints are drawn continuously, so the Map
view is useful standalone without an active trail recording.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
One character was too ambiguous to tell adjacent waypoints apart on the
map. Draw the first two characters of the label (falling back to one when
the label is a single char) in both the normal and degenerate map paths,
and widen the right-edge fit guard to the rendered text width.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Trail action-menu table gains Mark here / Waypoints / Clear waypoints.
- New Waypoints section: dropping (Mark here + label), independence from
the trail (/waypoints, survives reboot/Reset), map marker, the always-
present Trail-start row, the two-bearing nav view, and rename/delete.
- New Compass section: heads-up course-over-ground (no magnetometer),
rotating card, movement-only heading, GPS-fix gating.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds tools/trail_export.py: auto-detects the Wio port, waits for the
<?xml header, captures bytes until </gpx>, and writes a timestamped file
to tools/gpx/. Replaces the abandoned synthetic-FAT USB-MSC approach with
a simple host-side script.
- README: new "GPX Trail Export" section
- tools_screen.md: trail_export.py shown as the recommended download path,
cat/PuTTY kept as a manual fallback
- .gitignore: ignore tools/gpx/ output dir (mirrors tools/pngs/)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>