- BLE (ESP32): fast advertising (20-30 ms) for 30 s, then 152.5 ms, as the
nRF52 interface; the library default kept 30-60 ms forever
- Live map tiles: the WiFi drops after a minute with nothing missing
- ES8311 to standby while the I2S clocks are off, set up again before the
amp comes on
- Buzzer: no channel (DMA out of memory) waits out the samples instead of
spinning above the UI loop
- OTA: the image header check waits for its 16 bytes
- Comments: P10 is just the LED; the LCD SPI clock is 40 MHz on the wire
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The LoRa noise floor with the board's parts off one at a time, sweeps of
850-930 MHz, the mesh channel and a 7.8 kHz zoom on its loudest point; a
slow cycle of the same states for a second radio beside the device; and
a spike hunt over 864-876 MHz listing the lines over the floor and their
spacing (how the I2S MCLK comb was found).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One .vpk file per region in /vmap (header, sorted index of tiles and
points, then the data), read in place with the index in PSRAM; loose
{dz}/{x}/{y}.vt/.vp files still work. osm_vector.py writes packs
(--pack/--name), reads OSM PBF extracts for a box (--pbf/--bbox, via
pyosmium) and picks label languages (--lang). Map tools > Vector regions
lists the packs on the card: show one on the map, delete it. No
on-device download: packs are made with the tool.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
osm_vector.py --dem adds contours from the Terrain Tiles on AWS Open Data
(SRTM, ~25 m; tools/maps/dem.py, standard library only: PNG decode,
smoothing, marching squares, line joining). Every 100 m from zoom 12,
every 20 m from zoom 15; the credit names the elevation source.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Hiking routes are stored per stretch with the waymark colours of every
route along it and drawn as side-by-side stripes on a white band (half
the route ways in the Tatra sample carry two or more routes), less
simplified; demanding / alpine paths are dotted. Named points (places,
peaks with height, huts, passes, springs, viewpoints, caves) come in
small .vp files and are placed by priority as a layer over the tiles,
clear of each other and of the map controls.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Points as zigzag varint deltas, a byte length per feature to skip it,
natural land cover simplified harder: the Tatra sample goes from 4.4 MB
to 2.3 MB, panning at z14 from ~63 to ~45 ms per tile on the L2.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tools/maps/osm_vector.py turns Overpass JSON into VT2 tiles (data zooms
10/12/14, per-feature bbox, simplified); VectorTileProvider draws them
into 256 px tiles (scanline polygons, thick lines with round joins) with
a small PSRAM cache of data files. Behind Map tools > Vector map (test),
raster where there is no vector data.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Download an area: a frame with four corner handles on the map (kept in
world coordinates, the map pans / zooms under it); a bar gives its size,
zoom range, tile count and size, the trails switch and Get; areas on the
card are outlined
- Map tools > Map areas: the downloaded areas (map/AreaStore.h,
/sdcard/maps/areas.txt) -- show (framed, outlined), rename, fill gaps,
refresh (force re-download), trails on / off, delete (in steps, keeping
tiles another area covers)
- TileDownloader: force and per-job trails options
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A square grid drawn under the tiles (map, Nodes map, Home minimap), its step
a round distance for the zoom in metric or imperial units, with a scale bar
one step long; gives position and scale where no tile is loaded. The
missing-tiles hint moves up, off own position.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Waymarked Trails' transparent hiking layer, kept in /sdcard/maps-trails and
blended over the base tile at render time (Map tools > Hiking trails, NVS).
An area download fetches each tile's trails after its base tile, so
re-running an area on the card adds just the trails; with live tiles on, a
shown tile missing its trails has them fetched. Tiles without a trail are
stored as 0-byte files (no cluster on FAT).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Messages: New message moves to the header; Channels / Direct / Rooms fold
on a tap of their title (kept in NVS), a folded one shows its unread count
- Storage: the card's bar is split into one coloured segment per category
(plus the uncounted rest), each category row keyed with its colour
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Unread badge on Home tiles sits in the top-right corner, clear of the icon
- Minimap with no GPS fix: the saved position (hollow dot), else where the
map was left, else the default view; a hint when no tiles cover the area
- Screen header 38 px, so the back and header buttons get a margin
- Bluetooth / WiFi connected shown in the accent colour; charging bolt green
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Home pages: favourites, the clock (tap for Clock) with three telemetry
fields picked by holding one (shared dashboard_fields), a minimap that
frames you, live shares and the target (tap for the Navigation map), and
the apps in 3x2 pages. The side button now returns to the clock page with
a cross-fade instead of going back. Home moves to HomeScreen.h.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
group() / settingRow / listRow / actionRow / choiceRow / groupNote: one card
per section, hairlines between rows, hints that wrap. Dropdowns replaced by
a centred picker list. Settings regrouped (Device, Connections, Map & data,
System); Display & power split into Display, Power and Time on L2 only
(the shared schema is unchanged), Keyboard and About get their own pages.
Radio and Repeater share one LoRa parameter block.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Info cards drop the default 8 px row gap so text sits centred between
hairlines. The alarm Repeat list is compacted to fit above the dropdown.
creditText() keeps "(c) Name" and licence names like CC-BY-SA together
in About and the map credits toast.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shared infoCard/infoRow/infoNote helpers: muted label left, value right,
hairlines between rows, empty rows hidden. Diagnostics grouped into
sections with a received/sent packet table; GPS gets a position card and
constellation pills; About, OTA, Storage and map popups use the same
cards. Text no longer breaks after '.', clock alarm hint unclipped.
Sim-only sim_open() hook for jumping to a screen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Power: the UI loop sleeps until something is due (never with packets
queued); screen off puts the CPU at 80 MHz, the GT911 to sleep (unless a
tap wakes the screen) and the LP5814 in standby. GPS off now cuts the
L76K's rail and UART on the L2 (L2GpsProvider). The battery divider is
powered only for a reading (measured: settles at once); readings within
2 s are reused. The SD mount is retried at most every 5 s.
Fixes: WiFi left on after leaving a scan, live tiles' WiFi kept with the
screen off on the map, an ADC read every second for the status bar, touch
polled on every pass while dark, a scan cutting an update's WiFi, relay
count not refreshing in a channel thread, raw @[nick] in room previews.
Labels skip unchanged text (no redraw).
Helpers: scrollList, dimOverlay, settingRow, flexBox, nvs::get/put,
trailFilePath (a second save in the same minute no longer overwrites),
unreadTotal. Dead code removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mentions: "@[nick]" in message text becomes "@nick" in the accent colour
(a span group); a mention of us is underlined and its bubble outlined.
Chat previews and the message popup's quote show "@nick" as well.
Emoji: every single-codepoint Twemoji and every flag, 16 px RGB565A8 in
flash, as the fallback font of each text size (fonts/ui_emoji.c, data
generated by fonts/emoji.py). Joiners, selectors and skin tones take no
space; a regional-indicator pair is swapped for the flag's private
codepoint before text reaches a label. Twemoji credit in Settings > About.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shown while WiFi is switched on (Settings > WiFi), bright when connected
(live tiles, map download, update), dim otherwise. The switch is read
from NVS once and cached. The status icon signature buffer grew so
changes to the last icons aren't missed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The six slots with unread badges on a card of their own (swiped to,
no clock), redrawn when messages arrive; the Favourites tile and screen
are gone, showFavourites() opens the card. The page dots sit at the
bottom on every card.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Settings > Display & power > WAKE > Tap to wake (NVS, on by default):
off, only the top WAKE button turns the screen on. The side USER button
doesn't wake the screen any more (a press in a pocket); held, it still
mutes / unmutes with the screen off. Roadmap: buttons corrected (WAKE is
the top one), USER to open the main menu page later.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"solo", our version, upstream's and the build date (as digits) are drawn
in the wordmark's letters, the missing ones (l, v, d, digits, '.', '-')
made to match; a line with any other character falls back to Noto.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A progress bar and one line of counts while downloading (the zoom row
hides, it can't change then), failures on one line, the source as
"opentopomap.org", only the WiFi network's name (set up in Settings >
WiFi). The debug line (IP, RSSI, heap) is gone. Roadmap: mentions
highlight added, four items ticked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Status bar icons come from ui_icons_14: FontAwesome refitted to one
size by fonts/status_icons.py (falls back to ui_font_12 for the
battery level text), the charging bolt in a tight cell.
- Own channel posts show the repeater count as a small badge, as L1,
instead of a check and a number.
- Message path popup: a stronger connector, roles on the right
(sender / hop N / you), our post's repeaters fanned out under us,
long paths scroll.
- Scrollbars everywhere are thin and hug the edge, clear of the content.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tiles fetched while browsing online go to /sdcard/maps-live with an
index of arrival order; past the limit (Settings > Storage, 16 MB-1 GB,
default 64 MB) the oldest are deleted a few per loop. Storage shows
their count and size and can delete them all. Downloaded maps are never
touched. Roadmap: live tiles done, second batch of user items added.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The AW35615 USB-C controller (FUSB302-style registers, ID 0x91) only
reports VBUSOK with its measure block on; POWER resets to bandgap only,
so isExternalPowered() was always false. Board init turns it on
- Status bar shows a charge bolt on the cable, Diagnostics > Live has a
Power row, the GPS screen notes that charging disturbs GPS, and the
low-battery warning is skipped on USB as intended
- Roadmap: USB detection closed; GPS indoors still worse than the L1
even on battery, left open for later
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Home > GPS and Settings > System > GPS details: satellites on a sky plot
(filled = used in the fix, colour = C/N0), a bar per satellite with its
dB-Hz, fix state with time to first fix, DOPs, position, altitude, speed,
UTC and per-constellation counts; a Turn on button while GPS is off
- helpers/sensors/GpsSky.h parses GSV / GSA / GGA / RMC from any talker,
fed from MicroNMEALocationProvider behind -D GPS_SKYVIEW (L2 and the
sim only; L1 unchanged); the sim feeds it made-up NMEA
- Roadmap: GPS indoors diagnosed with it - on the USB cable the L76K
tracks satellites but never decodes navigation data; on battery it
gets UTC within seconds and a fix
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Tile fetch and OTA tasks run at idle priority: HTTPClient's read loop
only yields with delay(0), which at priority 1 starved IDLE0 until the
task watchdog reset the device (decoded from the core dump)
- A failed tile is retried once; failures in a row pause 5 s ... 60 s on
the same tile, and the download gives up only after ~5 min of nothing
- The source's last zoom level (OpenTopoMap 17, else 19, or line 3 of
source.txt) caps the download range and live tiles; past it the map
magnifies the parent tile
- OpenTopoMap's "no tile" picture is never saved, and copies saved by
earlier builds are dropped when read
- The placeholder check only runs on a fresh area and for pictures with
content: plain sea / empty land tiles are genuinely identical
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Message history archived per conversation on the SD card (HIST_ARCHIVE):
restored on boot, Older/Newer paging in threads, kept count selectable
- Settings > System > Storage: card and flash usage, breakdown by maps,
messages, trails and other, kept-per-chat setting, delete history;
reads the mounted volume and warns when the FAT partition is much
smaller than the card
- Saved trails on the card: every Save is a new file, Load opens a list
with load (framed on the map), GPX export and delete
- Diagnostics: GPS data rows, last start reason, last crash summary
- Messages restored before the clock is set show their date instead of 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Unlocking fades the lock screen out while the screen underneath drifts
into place; the slider unlocks on letting go at the end and springs back
when let go earlier
- Channel names no longer get a "# " prefix (thread title, channel popup,
live share targets) -- "#" marks a hashtag channel; favourite contacts in
the live share list are starred instead
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Anim.h: screens emerge from the middle (background cover fades, content
drifts 6 px), Home pages slide, popups and toasts rise and fade in
- Theme.h: accent rules (fill = primary action, dim fill = selected, text =
names/counts/modes), theme layer over the default theme, radius tokens,
accent colour picker (Settings > Display & power > LOOK, NVS mc_ui)
- Splash with the Solo and upstream versions
- Status icons in equal cells, L1-style relay marks, path window with a hop
diagram, tile download popup fits the screen (WiFi only in Settings)
- Perf: uncompressed fonts, two 120-line PSRAM buffers (~48 -> ~33 ms per
transition frame); UI_PERF_TEST harness
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Screen PIN (Settings > Display & power > Security): 4-8 digits in NVS,
keypad on the lock card after every wake and on boot, 5 misses -> 30 s pause
- Live map tiles: missing tiles at the current zoom are fetched over the saved
WiFi, written to the card and drawn; WiFi drops 30 s after leaving the map;
"Live tiles" switch in Map tools
- Firmware update (Settings > System): checks the fork's latest release,
streams the -ota.bin into the spare app slot over TLS verified with the
Arduino 3.x CA bundle, checks image magic/chip id, restarts
- Release workflow publishes *_solo_lvgl envs (merged image + -ota.bin)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Map tools hold trail, live share and arrival alert, with their options
(schema page "Map options") behind one button; back returns to the map
- Nearby gets an advert button: send now (nearby / everyone) + auto-advert
- Home page 3: Repeater, Admin (list of repeaters and room servers),
Diagnostics
- Settings: display, sound, radio (Bluetooth, WiFi), system, keyboard,
contacts & messages; units moved to Display & power
- Status bar: Bluetooth, GPS, alarm, mute, then auto-advert, trail, live
share, repeater, arrival alert in the accent colour
- Fonts: key and route glyphs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- New env Wio_Tracker_L2_companion_solo_lvgl_v3 on pioarduino 55.03.312-1;
the 2.0.17 env stays until the new one passes the hardware checklist
- SerialBLEInterface: NimBLE variant (PIN pairing through encrypted,
authenticated characteristic properties; setAccessPermissions is a no-op)
- buzzer: i2s_std driver on IDF 5 (legacy driver kept for 2.0.17)
- ESPNOWRadio: IDF 5 callback signatures
- ui-lvgl: psramBuf() for trail drawing, tile cache, map marks, list rows,
keyboard maps and message metadata; internal heap back to 2.0.17 level
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- genericBuzzer I2S path (BUZZER_I2S): an audio task synthesises the notes
with eased edges and keeps the DMA queue fed with silence between sounds;
ES8311 setup; amp powered through the board only around sounds
- ui-core/SoundControl.h (mode, volume, built-in sounds, melody model),
SoundNotifier moved to the Core, chanctl::melody, schema Sound page
- L2: notifications, alarm / timer ring, locator sounds, Settings > Sound,
melody editor with the playing note lit, per-chat sound, mute icon
- noteIndex() on every buzzer backend; scrolling popups past screen height
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
BotConfig (tabs, rows, the NodePrefs field behind each, reply placeholders)
moves into ui-core; ui-new's Tools > Bot renders it. L2: Home > Bot with
switches, list pickers, text popups with placeholder buttons, quiet hours.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AdminSession (login with saved password, CLI round trips, timeouts, field
table, typed values) moves into ui-core; UiCore offers login answers and
CLI replies to it first. ui-new's Tools > Admin becomes a view over it.
L2: node detail > Admin with tabs and per-field popups.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ChannelControl (add Public/Hashtag/Private, rename, delete, notif/fav/scope)
and Favourites slots move into ui-core; ui-new uses them. Contact / channel
pref cleanup moves from ui-new's UITask into UiCore so it runs on every
frontend (L2 had none). L2: channel options popup (hold a row or the gear
in a channel) and the Add / Edit channel form.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Shared by ui-new (L1) and ui-lvgl (L2) so both firmwares have the same core
features:
- WaypointModel (/waypoints, UTF-8-safe labels, [WAY] share text),
EtaTracker, GpsAverager, TrackBack; TrailEngine save/load/reset actions;
UiCore::setGpsEnabled / applyGpsInterval.
- Locator target kind 2: a channel live share followed by sender name
(LiveTrackStore::activeByName).
- SettingsSchema: pages (navigation, display & power, messages & contacts),
value tables over 1/2/4-byte NodePrefs fields, side effects via UiCore.
- RadioControl: apply params / TX power / APC and the preset list; ui-new's
Settings > Radio now goes through it.
- NodePrefs::display_brightness_pct (sentinel 0xC0DE002F, size unchanged)
for frontends with a brightness slider.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>