Commit Graph
1593 Commits
Author SHA1 Message Date
JakubandClaude Opus 5.5 abbbdc5ae5 perf(l2): cheaper frames -- less overdraw and blending
Measured on the L2 (steady full frames): Settings page 37.7 -> 31.4 ms,
Display 41.5 -> 37.9, Contacts 34.6 -> 32.9, Home 37.3 -> 32.4.

- styleSurface() leaves boxes in the page colour unpainted; styleOpaque()
  for the screen and the status bar, which things slide under.
- group() cards clip their corners only while a row is held
  (rowPressable(), shared by the tappable rows).
- rowSlider(): the track an opaque tint (theme::mix(), also behind
  ACCENT_DIM) instead of 20 % accent blended every frame.
- Map buttons, pills, scale, nav bar and the Home minimap labels opaque.
- Screens drift in without the fading cover: its full-screen blend was in
  every entrance frame (page 39 -> 29 ms).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 14:30:45 +02:00
JakubandClaude Opus 5.5 f29c280c34 perf(l2): map tiles decode with PNGdec
PNGdec (bitbank2, 1.1.6) decodes a tile a row at a time straight into
RGB565, without lodepng's 256 KB RGBA buffer; the trail overlay goes through
it too, blended by hand for palette-with-alpha and RGBA. It lives in its own
file (ui-lvgl/TilePng.cpp) because its zlib headers put DONE/EXTRA in the
global namespace. lodepng stays the fallback and the sim's decoder.

Same 20 tiles: decode 78 -> 50 ms, trails 42 -> 17.5 ms, a whole tile
170 -> 105 ms; the map with trails is pixel-identical.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 08:53:15 +02:00
JakubandClaude Opus 5.5 039485bf34 perf(l2): heavy screens build in pieces over several loop passes
The list fill becomes a small job queue (fill/then/fillStart, fillTick with a
25 ms budget per pass). Settings pages build section by section in
schemaRows, with the trailing extras (melodies, prune, quick messages) queued
after them so the order stays; Radio and Repeater build by group, Admin's
repeater pick like the contact list, Diag's Live tab by section. Rebuilds
that restore the scroll flush the queue first. Screens went from 220-360 ms
to 80-175 ms (build + first frame).

Diag's crash line read the core dump in flash every second (~44 ms each);
it is read once now. The perf run times every page and dismisses the USB
popup, which had covered all earlier measurements.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 08:53:15 +02:00
JakubandClaude Opus 5.5 34f739c45b perf(l2): long lists fill in over several loop passes
A widget costs ~1 ms on the L2, so Nodes with 48 rows held the screen for
~600 ms and a full contact list for over a second. fillStart() builds the
first screenful at once and fillTick() adds the rest ~25 ms a pass.

- Nodes: 6 rows first; the 2 s refresh rewrites built rows in place
- New message: contacts filled the same way
- Settings: a group at a time (all at once when coming back scrolled)
- Nodes 671 -> ~200 ms, Settings 376 -> ~190 ms longest UI stall

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:24:57 +02:00
JakubandClaude Opus 5.5 247fab08d0 perf(l2): map tiles decode on the other core
- TileCache: request() hands z/x/y to a task on core 0, which renders into
  a spare buffer; poll() swaps it into the LRU slot (stale results dropped
  after drop()/invalidate()); the sim runs the job at once
- MapScreen / Home map place finished tiles as they arrive; the longest
  UI stall with the map opening goes from ~340 to ~170 ms
- LVGL allocates from the PSRAM heap (lv_mem_psram.h), safe from both
  tasks; LVGL's own pool is gone
- lv_conf: notes why LV_OS_FREERTOS with two draw units stays off
  (measured slower: drawing is bound by PSRAM bandwidth)
- UI_PERF_TEST: the map (tile read/decode, pan, redraw), build time and
  the longest loop pass per screen

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 00:24:57 +02:00
JakubandClaude Opus 5.5 b3b77a1f6d feat(l2): long trails with a card copy; map follow and redraw fixes
Trail on the L2: 32768 points every 5 m, no simplification, no point
spacing setting; copied to the card every minute and restored at power-on.
The line keeps up with the position dot (incremental sync, pending point).

Map: a tap's finger jitter no longer turns follow off; the GPS button
shows when the map follows. The trail is drawn as one polyline with
breaks and off-view chunks skipped (an lv_line queued a draw task per
point).

Fewer rebuilds: conversation bubbles patched (new messages, delivery
marks), home mini-map dots reused, Nearby rows rewritten in place,
history read in runs and each file opened once.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:02:49 +02:00
JakubandClaude Opus 5.5 5f6cbe34b3 fix(ui-lvgl): tile downloads ride out server errors instead of stopping
503/429 slow the pace down, transport errors retry after 2/8/30 s, failed
tiles get a second pass; the download only gives up after 10 minutes
without a single tile or on repeated 403s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 22:02:49 +02:00
JakubandClaude Opus 5.5 9938ae7a2d chore(ui-lvgl): comments name the real Settings pages
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 13:27:34 +02:00
JakubandClaude Opus 5.5 e4d24650c5 feat(l2): screenshots over USB (RGB565); USB tools moved to the Solo site
- CMD_GET_SCREENSHOT on colour screens: display type 2 (RGB565 LE),
  32-bit payload size; ui-lvgl captureFrame() shared with the SD BMP
- ENABLE_SCREENSHOT in the L2 build; tools/screenshot.py decodes type 2
- docs and READMEs point to solo.marekzegarek.com/#pc-tools
- USB popup: "Keep card" instead of "Charge only" (only the card is lent;
  charging and USB serial work either way)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 12:27:59 +02:00
JakubandClaude Opus 5.5 4ab9d949ec perf(ui-lvgl): lower clock when idle, fewer redraws, wake on BLE frames
- CPU at 80 MHz with the screen on after 2 s without touch or animation;
  a touch restores the full clock before its frame is drawn
- setText(): periodic refreshes no longer redraw unchanged labels
  (status bar, Home, lock, Diag, GPS, compass, clock, map, nav, nearby)
- map markers kept across the 3 s rebuild when unchanged
- app connected: the loop blocks until a BLE frame arrives
  (serialFrameArrived / hasPendingFrames) instead of polling every 2 ms
- PSRAM: boot frame sprite and the HTTP response buffer released

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 11:51:18 +02:00
JakubandClaude Opus 5.5 bc266a4f5c fix(ui-lvgl): smooth WiFi/Bluetooth switches; retry 404 tiles
- The WiFi and Bluetooth rows rebuilt the whole Settings page to update
  their hint, cutting the switch's animation short; the hint is now
  rewritten in place (rowHintSet). The "Bluetooth on" echo toast is gone.
- Map download: a 404 gets the same one retry as other errors
  (OpenTopoMap sends the odd 404 for a tile not rendered yet), and a
  download that ends with gaps says "Done, N missing - download again".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 10:41:18 +02:00
JakubandClaude Opus 5.5 890ee6533e build(sim): colour-touch (ui-lvgl) WASM in the solo-sim release zip
- build-solo-sim.yml clones LVGL at the version pinned in
  solo/wio-tracker-l2/platformio.ini and builds the SIM_UI=lvgl sim into
  wasm/lvgl/ of solo-sim-wasm.zip, for the site's device switch.
- build_wasm.sh: LVGL_DIR can be overridden (CI has no .pio libdeps).
- sim_test_set_node_name(): names a sim node, for site screenshots.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 10:18:39 +02:00
JakubandClaude Opus 5.5 e822242660 docs: stage I3 -- documentation rewritten under docs/solo
Short pages by feature (getting started, messages, contacts, navigation,
tools, settings, lock, hardware) instead of one page per OLED screen, with
Wio Tracker L2 differences as notes; facts checked against the code
(keyboard scripts vs. hold-for-accents, {batt}/{dist}, L2 limits and
settings layout). Developer guides and build flags under docs/solo/developer.
Old docs/solo_features and its ~50 screenshots removed; a hero banner and
three simulator screenshots added; links updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 08:41:10 +02:00
JakubandClaude Opus 5.5 3adf0b0436 chore: stage I1 -- repo cleanup, minimal README
Working plans (docs/development, docs/design redesign notes) removed; the
two developer guides moved to docs/developer/. README cut to devices,
flashing, links and building (Wio Tracker L2 added); its feature list and
doc tables moved to docs/solo_features/README.md. RELEASE.md describes the
Solo release flow. Upstream's GitHub Pages workflow (docs.meshcore.io)
dropped, CLAUDE.md untracked, Buy Me a Coffee back in FUNDING.yml.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 07:36:15 +02:00
JakubandClaude Opus 5.5 e28b5c5c51 fix(ui-lvgl): no USB drive behind the screen PIN; drop the NVS PIN migration
The SD card (message history) could be lent to a computer from the lock
card before the PIN was entered. While locked with a PIN, usbPoll() no
longer reacts; a cable plugged in meanwhile is offered once unlocked.

The plain-text NVS PIN never shipped, so there's nothing to migrate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 00:13:33 +02:00
JakubandClaude Opus 5.5 4bda4f3a76 fix(ui-new): keyboard letters were blank
Since bf1e6fca kbApplyCapsUtf8 wanted 4 bytes free before each codepoint;
the ABC grid passes a 3-byte cell buffer, so every cell came out empty (T9
and CardKB Compact draw no such cells, so it went unnoticed). A codepoint
is now copied when it fits with the NUL.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 00:06:01 +02:00
JakubandClaude Opus 5.5 358f92222a Merge PR #37: lock screen PIN (3urobeat), adapted
The contributor's feature -- a PIN asked before the screen unlocks, on
boot, and when the magnet cover opens, stored as a salted SHA-256 -- on
top of this branch, with:

- ui-core/ScreenLock.h: set / check / isSet and the tries limit, shared by
  L1 and L2. isSet looks at every byte (the PR tested only the first, so one
  PIN in 256 silently disabled the lock). 5 misses pause entry for 30 s.
- NodePrefs: the fields at the tail after quiet hours, sentinel 0xC0DE0031,
  sizeof 2880; an older file's bytes there are cleared. A sentinel bump no
  longer resets display_brightness_pct from a file that already has it.
- DataStore: no AGPL header (the project is MIT), no whitespace churn.
- Keyboard: the number pad is a widget flag (pin_mode) with a prompt in the
  preview ("New PIN", "Again", "PIN"), not keyboard_type = 2 written into the
  prefs and restored after.
- L1 Settings: "Lock PIN" right after the schema's "Lock screen" row, typed
  twice, at least 4 characters, saved at once (a power-off right after
  setting it kept no PIN). Home is told about a boot-time lock once it
  exists (also fixes booting with the cover closed).
- L2: the screen PIN moves from plain text in NVS to the same hash in
  NodePrefs; the old one is migrated on first boot and removed. The pad
  unlocks as soon as the hash matches from 4 digits on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-29 00:06:01 +02:00
JakubandClaude Opus 5.5 0e1b3c9cfd fix(companion): signing takes the buffer it can get (#38)
CMD_SIGN_START promised the app 8K before a malloc it never checked. On
the L1 the nRF52 heap has ~5K free from boot, so the malloc always failed
and every CMD_SIGN_DATA answered ERR_CODE_BAD_STATE. Now it allocates
first, halving down to 256 B, and reports the size it got; nothing at all
is an error on SIGN_START itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 23:34:29 +02:00
JakubandClaude Opus 5.5 b355922d32 feat(companion): core parity -- L1 sends via the core, shared telemetry, schema settings on L1
- L1's MessagesScreen sends through UiCore::sendDirectText / sendChannelText
  (its own copy of send + file + ACK tracking gone).
- ui-core/Telemetry.h: the dashboard fields (numbers, names, formats) and
  sensor readings as text, each frontend passing its Style; L2 Home, L1's
  clock page, lock screen, sensors page and GPS altitude use it.
- L2: the side button held in the first 8 s is the CLI rescue, as on L1.
- L1's repeater radio goes through rptctl.
- L1 Settings are built from SettingsSchema: short labels for small
  screens, SCHEMA_* placeholders expand to the schema's sections, one
  generic row (switch ON/OFF, bars for brightness / volume). 20 hand-written
  rows and their tables gone; L1 implements applyDisplayPrefs /
  applySoundPrefs. settings::text / step / indexOf shared with L2.
- Schema: auto-off gains 5 s; the advert sound scope reads "Direct".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 23:19:47 +02:00
JakubandClaude Opus 5.5 ece849db3b refactor(ui-lvgl): review -- shared button bar, confirms, notes, local time
- Dead code gone: anim::fadeHide, radioctl::presetCount, the L2 board's
  setSdPower / setGrovePower / expanderOK (awRead, gnssReset now private).
- buttonBar() / barButton() replace 7 copies of the popup button row.
- confirmBody(): one red-button confirm for reboot / power off, reset
  counters, admin commands, preset and scope delete.
- tapConfirmed(): the 11 "tap again" buttons share one mechanism, 3 s
  everywhere, the label restored when left alone.
- noteLabel() for ~30 wrapped notes.
- localTm() in NodePrefs.h and one MONTHS table: lvgl, MsgExpand, the L1
  clock and lock screen.
- The sim keeps UI settings in an in-memory nvs::, so one set of load /
  save helpers serves both.
- Asleep, the loop wakes every 50 ms (the button / touch poll), not 20.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 22:35:26 +02:00
JakubandClaude Opus 5.5 1def29335c feat(companion): quiet hours -- muted on a schedule, the alarm still rings
Settings > Sound > Quiet hours (L2: its own group; L1: Quiet hrs / from /
until): from quiet_from to quiet_to (local hours, wrapping past midnight)
the buzzer is muted and a message doesn't wake the screen; the clock alarm
still rings. A manual mute or unmute inside the window stands until the
window ends. Off with the clock unset.

NodePrefs gains quiet_hours / quiet_from / quiet_to (appended to the file,
sentinel 0xC0DE0030; sizeof 2832 on nRF52 and ESP32), off by default,
22:00-07:00. hourInWindow() / localHour() are shared with the bot's quiet
hours. soundctl::tick() replaces autoTick() (Auto and quiet hours).

Also fixes the L2 side-button mute: it went by the mode, not by whether
the buzzer was muted, so with Auto + an app connected (and now quiet hours)
the first press muted instead of unmuting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:59:40 +02:00
JakubandClaude Opus 5.5 2e9654fd1c refactor(ui-lvgl): Diagnostics > Noise is one measurement for any board
The Noise tab held the L2's interference hunt: parts of the board off one
by one, a slow cycle for a second radio, a spike hunt and three sweeps
(~90 s, L2 only). It is now one Measure: the noise floor on the mesh
frequency (median and 10th percentile of 5 s) and a +-1.1 MHz sweep round
it, ~12 s, with a short legend for reading it. Works wherever the variant
defines the radio.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:41:16 +02:00
JakubandClaude Opus 5.5 e47738ce01 feat(ui-lvgl): map tools regrouped; a map area previews when picked
Map tools: TRAIL, LIVE SHARE and ARRIVAL ALERT each with their own options
page (that section of Map options; back returns to Map tools), the arrival
alert switch where its state is shown, OFFLINE MAPS (Map areas, Live
tiles; the separate Download an area is gone -- a running or unfinished
download shows at the top of Map areas) and LAYERS.

Map areas: picking one frames it on the map above a small sheet (no Show
button, the map above isn't dimmed); closing the sheet, however it's
closed, puts the map back where it was and drops the outline -- it used
to stay on the map. New popup kind POP_BOTTOM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:30:46 +02:00
JakubandClaude Opus 5.5 a11df8431b fix(ui-lvgl): 16 KB UI stack (screenshots reset the device); USB popup after the splash
The UI runs on Arduino's loop task, whose stock 8 KB stack had 340 B left
at its deepest point; a screenshot's file write went past it and reset the
device. The loop stack is now 16 KB (measured peak ~7.8 KB) and the
screenshot's line buffer is static. Diagnostics names the row
"UI stack free (lowest)".

With a cable in at boot, the USB popup waited for nothing and showed over
the splash; it now comes once the splash has faded.

Adds docs/development/plan-next.md, the plan up to the merge into dev.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 21:30:46 +02:00
JakubandClaude Opus 5.5 7a21e58c54 feat(ui-lvgl): arrange Home's apps -- drag to move, tap to hide
Hold an app on Home (or Settings > Home apps) to arrange them: every app
is shown, hidden ones dimmed with a +; a drag drops the app into the slot
under the finger, held at a screen edge it goes to that page; a tap hides
or shows it. Settings stays shown. The order is kept in NVS (letters per
app, lower case = hidden), saved on Done or on leaving Home.

Roadmap: note the speaker-knock experiment (DAC ramp didn't help).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:29:00 +02:00
JakubandClaude Opus 5.5 51530ac451 feat(ui-lvgl): SD card as a USB drive, message banner, card format, restart screen
- USB through TinyUSB (ARDUINO_USB_MODE=0) instead of USB-Serial/JTAG: the
  serial port stays, and plugged into a computer (enumerated, the bus not
  suspended -- on battery an unplug only shows as a suspend) the device asks
  "Charge only / USB drive". As a drive the firmware lets go of the card and
  the computer gets its sectors; ejected or unplugged, the device restarts.
- Incoming messages: a banner slides down from under the status bar (icon,
  sender or channel, two lines of the text from history); a tap opens the
  conversation (not while locked), a swipe up dismisses it, not shown for
  the conversation already open. Toasts moved up there too, under the banner
  when both are up; the ones only echoing a switch or a choice are gone.
- Storage > Format card: a popup saying what goes, then Format tapped twice;
  one FAT32 volume over the whole card (readable or not), then a restart.
- A deliberate restart shows a full "Restarting..." screen with the reason
  instead of the screen just freezing.
- The screenshot flash is a thin frame round the edges: a full-screen fade
  redrew all 320x240 each step and tore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 17:17:38 +02:00
JakubandClaude Opus 5.5 95c4c093f0 feat(ui-new): Tools > Satellites -- sky plot and signal bars on the 128x64 OLED
Two views, swapped with left / right: a polar sky plot (filled = used in the
fix, hollow = tracked, a pixel = no signal) beside fix, used / in view, HDOP,
PDOP and time to first fix; and a signal bar per satellite (used first, a
dotted 30 dB-Hz line) under per-constellation counts. The GPS stays awake
while it's open. Data from GpsSky (-D GPS_SKYVIEW, now on the L1 solo build).
The simulator's made-up sky moves from the L2's GpsScreen into
helpers/sensors/GpsSkySim.h, so both sims show it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:33:41 +02:00
JakubandClaude Opus 5.5 e82cedaf23 feat(ui-lvgl): several saved WiFi networks, joined by signal; Save checks the password
- Settings > WiFi keeps up to 8 networks (NVS "s0".."s7" / "p0".."p7"; the
  single one older builds saved moves over). A tap loads one to change its
  password, Forget asks with a second tap, a scan marks the known ones.
- Map downloads, live tiles and updates join the strongest saved network in
  range (a short scan first when more than one is saved), else the newest
  one -- which also covers a hidden network.
- Save joins the network once: "password OK", turned away (forgotten again,
  the form keeps it to fix) or not in range (kept, checked later).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:24:10 +02:00
JakubandClaude Opus 5.5 2765ac6d8b feat(ui-lvgl): screenshots (side + top button), lock screen always times out
- Side button held + top button saves the screen, popups and toasts included,
  to /sdcard/screenshots/scr_NNNN.bmp (24-bit BMP). The flush callbacks copy
  one forced full re-render into a PSRAM buffer. A white flash and a toast
  confirm it. The side button's mute now fires on release, so holding it a
  little long before the top button doesn't also mute. In the sim, the page's
  Screenshot button downloads the file.
- The lock screen goes dark after 30 s even with auto-off at Never (a boot
  PIN, a pocket wake-up, a message), and sooner if auto-off is shorter.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 16:03:48 +02:00
JakubandClaude Opus 5.5 cf9ffc29b0 feat(wio-tracker-l2): internal flash as LittleFS instead of SPIFFS
helpers/esp32/InternalFS.h picks the filesystem: -D ESP32_LITTLEFS mounts
LittleFS on the same "spiffs" partition, otherwise SPIFFS as before. Only the
L2 LVGL envs set it; every other ESP32 board is unchanged. A settings save
drops from ~0.5 s to ~80 ms and the files survive power loss mid-write.
No migration: the first boot formats the partition (fresh identity).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 15:47:57 +02:00
JakubandClaude Opus 5.5 063f81e1df perf(ui-lvgl): save settings on leaving the screen, not on every toggle
Every toggle / stepper wrote the prefs file straight away (0.1-0.6 s on the
ESP32's SPIFFS), which stuttered the UI and wore the flash. prefsSave() now
only marks them dirty; they're written once when the screen is left, when the
display goes off, or after 60 s at the latest -- the L1's approach. Shutdown
and the pre-restart OTA save still write immediately.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 15:47:57 +02:00
JakubandClaude Opus 5.5 350393436a feat(ui-lvgl): AM / PM beside the big clock on a 12-hour clock
It was a muted prefix on the date line, easy to miss. clockFace() -- the
digits and a small AM / PM on their baseline -- is shared by Home and both
lock screens (the PIN card showed no AM / PM at all). The date loses the
prefix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 15:19:10 +02:00
JakubandClaude Opus 5.5 ed5c903c3b build(wio-tracker-l2): LVGL 9.2.2 -> 9.6.0
The triangle draw descriptor's colour fields lost their bg_ prefix and style
getters take an lv_part_t. 9.6 sizes flex containers through the layout, so
popups no longer shrink when pulled past their end: lvgl_patches.py goes.
The sim wipes its LVGL object cache when the library version changes.
Flash +73 KB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 15:06:23 +02:00
JakubandClaude Opus 5.5 9d4f018696 fix(ui-lvgl): popups no longer shrink when their list is pulled past its end
LVGL 9.2.2 measures a SIZE_CONTENT box from its children as scrolled, so an
elastic pull past the end of a capped popup list shrank it by the overshoot,
again on every pull. lvgl_patches.py fixes calc_content_height in the
downloaded library (a build middleware for PlatformIO, called directly by the
sim's build_wasm.sh).

The five popups that each built the same panel now share popupOpen() (fit to
content / full height / under the status bar).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 14:45:19 +02:00
JakubandClaude Opus 5.5 4431d754a2 fix(ui-lvgl): drop the GPS screen's USB-charging warning
The GPS trouble on the cable was the I2S MCLK comb (fixed in b50ecc83):
fix times match with and without USB now.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 14:20:49 +02:00
JakubandClaude Opus 5.5 958627d6e9 fix(wio-tracker-l2): radios and codec idle when unused; buzzer and OTA fixes
- 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>
2026-09-27 14:13:39 +02:00
JakubandClaude Opus 5.5 782f8aa567 feat(ui-lvgl): Diagnostics > Noise tab for RF noise hunting
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>
2026-09-27 13:54:25 +02:00
JakubandClaude Opus 5.5 002f478231 feat(ui-lvgl): vector region packs, PBF input, region list
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>
2026-09-27 13:54:25 +02:00
JakubandClaude Opus 5.5 16144bd48b feat(ui-lvgl): contour lines on the vector map
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>
2026-09-27 11:35:21 +02:00
JakubandClaude Opus 5.5 117b7513bc feat(ui-lvgl): vector map route stripes and point labels
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>
2026-09-27 11:25:08 +02:00
JakubandClaude Opus 5.5 ba4e13e2b2 feat(ui-lvgl): VT3 vector tiles, delta varint points
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>
2026-09-27 10:41:01 +02:00
JakubandClaude Opus 5.5 1973361244 feat(ui-lvgl): vector map spike (own VT2 format from OSM)
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>
2026-09-27 10:31:33 +02:00
JakubandClaude Opus 5.5 c90cf474fe feat(ui-lvgl): pick download areas with a frame, list of map areas
- 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>
2026-09-27 09:51:29 +02:00
JakubandClaude Opus 5.5 00e961ca63 feat(ui-lvgl): grid and scale bar under the map
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>
2026-09-27 09:39:37 +02:00
JakubandClaude Opus 5.5 ad890a49f6 feat(ui-lvgl): hiking trails overlay on the map
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>
2026-09-27 09:32:00 +02:00
JakubandClaude Opus 5.5 8b231935ba feat(ui-lvgl): foldable Messages sections with New in the header, storage bar by category
- 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>
2026-09-27 09:08:25 +02:00
JakubandClaude Opus 5.5 5289f6b11a fix(ui-lvgl): tile badges in the corner, minimap without a fix, taller header, accent status icons
- 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>
2026-09-27 01:41:46 +02:00
JakubandClaude Opus 5.5 e52ec2a97e feat(ui-lvgl): phone-style Home -- clock with telemetry, minimap, app grid
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>
2026-09-27 01:30:12 +02:00
JakubandClaude Opus 5.5 a40a87d02c feat(ui-lvgl): settings kit, choice picker, reorganised Settings
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>
2026-09-27 01:17:48 +02:00
JakubandClaude Opus 5.5 e502a491f4 fix(ui-lvgl): tighter info rows, clock repeat list fits, credits wrap cleanly
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>
2026-09-27 00:42:35 +02:00