Commit Graph
4339 Commits
Author SHA1 Message Date
JakubandClaude Opus 5.5 b17f97c71f fix(l2): quick panel stalled and tore when pulled; GPS sky plot cut off
The panel froze and dimmed the screen as the finger started: a snapshot of
the whole screen (slow on the map) and a full-screen flush, so it stalled,
jumped and tore top to bottom. Now it slides opaque over the live screen
(a clear layer under it still takes the tap that closes it), built at start.
Its slide is timed by its own frames, at most 30 ms a frame: a slow frame
ended the 160 ms lv_anim and the panel just appeared.

The sky plot on GPS > Sky was a fixed 168 px, taller than what is left
under the title bar and tabs: now it takes that height.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 23:24:52 +02:00
JakubandClaude Opus 5.5 743500761a feat(l2): light theme reworked - a tint for selected, grey values, quiet edges
The light theme read as the dark one inverted. Now something selected (a
tab, a segment, a tile, Fav) is a tint of the accent with the accent's text
(SEL_*), the full accent fill stays for the primary action; setting values
read in grey (VALUE); popups, the banner and the toast have a quiet grey edge
(EDGE), the toast is a dark pill; neutral greys the RGB565 panel keeps
neutral; the big clock graphite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 23:24:46 +02:00
JakubandClaude Opus 5.5 76e96f7eaa feat(l2): light theme
Settings > Display > Theme: Dark / Light (NVS mc_ui/light). The colour
tokens are set once before anything is built, so a change restarts the
device. Text on an accent fill is the new ON_ACCENT (it was BG, white
in the light theme); each accent has a deeper hand-picked light variant
that reads on white and takes white text. The map's empty-tile fill and
grid and the areas' outlines follow the theme too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:55:47 +02:00
JakubandClaude Opus 5.5 e5a55c3b1f feat: flashlight - the whole screen white at full brightness
L2: a Flashlight app on Home (a lightbulb icon added to the fonts): a
white layer over everything, the backlight at 100 %, no auto-off; a tap,
the side or the top button puts it away and the brightness back.
L1: Tools > System > Flashlight, the whole OLED lit at full contrast
until a key. Not on e-ink.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:55:01 +02:00
JakubandClaude Opus 5.5 06a188d572 fix(l2): quick panel - the screen showed through its rounded top corners
The panel starts a radius up, under the status bar, so its top corners
are hidden there instead of cut out over the frozen screen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 22:54:56 +02:00
JakubandClaude Opus 5.5 b4ec5dcb54 feat(map): base layers - Topo, Light, Dark, Satellite, Esri Topo
Map tools > Layers > Map picks what the map is drawn from:
- Topo: OpenTopoMap, as before.
- Light and Dark: Esri's grey canvases, no labels, up to z16.
- Satellite: Esri World Imagery.
- Esri Topo.

Each layer has its own folder for downloaded areas (/sdcard/maps-light,
-dark, -sat, -esritopo; Topo stays in /sdcard/maps) and its own live-tile
cache. Live-cache records carry the layer.

Esri serves JPEG: decoded with LVGL's tjpgd (LV_USE_TJPGD), whatever the
file name says. The layer is kept in NVS (mc_ui/layer); switching waits
while a download or a deletion runs in the current folder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:25:16 +02:00
JakubandClaude Opus 5.5 85ef06b6be feat(map): packet flow shows all traffic - kinds in colours, a legend, its own nodes
- Every packet heard is drawn, by kind in fixed colours: advert, DM,
  channel, request, ack, other, sent. One that can't be placed on the map
  is a ring at your own position.
- A legend pill at the top counts each kind over the last minute.
- On a map without node markers, a flow brings its own nodes (a dot and
  the name), fading with it.
- Copies of one packet (the same packet hash) share one fade, so a path
  goes out as a whole, not segment by segment.
- 32 flows kept on ESP32 (12 on nRF).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:24:24 +02:00
JakubandClaude Opus 5.5 2f2db6045c fix(l2): WiFi fails to start or join - big statics and task stacks to PSRAM
WiFi starts and joins on internal RAM: ~42 KB the first time, ~25 KB after,
more for WPA. Free internal RAM had shrunk to ~20 KB after opening the map
(the tile decoder's 12 KB stack, the 32 KB I-cache, the DMA draw buffers,
UI statics), so a scan failed at once (esp_wifi_init: no memory) and a join
during a tile download timed out (AUTH_EXPIRE).

- ESP-IDF: CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY, and the esp_timer
  task stack 8 -> 4 KB (it uses ~0.4 KB). Rebuild the framework libs:
  pio run -e Wio_Tracker_L2_idf_libs.
- PSRAM_BSS (EXT_RAM_BSS_ATTR) on the UI's big statics: QR codes, map
  state, charts, lists. .dram0.bss 115 -> 66 KB.
- The tile decoder's and fetcher's task stacks in PSRAM.

Free internal RAM, idle: 48 -> 105 KB; WiFi up: 57 KB, 29 KB at the
lowest while downloading tiles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 17:23:29 +02:00
JakubandClaude Opus 5.5 3825dcc077 fix(l2): fast typing - a second finger is a new tap, not a slide
With two thumbs the second lands before the first lifts; the panel's
first point then jumped to it and LVGL saw one press sliding from key to
key, losing the first letter (or starting a scroll). A new GT911 track id
is now a release, then a press. The keyboard no longer hands a rolling
finger to a scroll or gesture up the tree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:51:03 +02:00
JakubandClaude Opus 5.5 c779bf46b5 feat(ui-lvgl): title bar with the clock, tidier controls, contextual nav bar
Density from less chrome instead of smaller rows (ROW_H stays 44):
- titled screens drop the status bar; the title bar (APPBAR_H) holds back,
  the title, the screen's actions and the time/battery on a pill; the status
  bar returns for Home, the map, typing, the quick panel and the lock
- one radius (RADIUS) for everything tapped: buttons, tabs, choices, chips
- tabs are all segmented at TAB_H in the body (GPS, Clock converted)
- Nodes: chips row + sort + status line become one toolbar row with
  Show / Order choices; Messages' All/Favourites is the same choice
- nav map: the target bar only while there is a target; the pin opens one
  "Places" popup; back from a map options page restores the map and Map
  tools as left, without a jump
- node detail actions at the top of the scroll; Home tiles fill the page
- rowsFit() leaves growing labels to the flex (a screen title cut to one
  letter after Messages' filter changed)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:51:03 +02:00
JakubandClaude Opus 5.5 a8440c890e feat(map): packet flow - what the radio hears, as lines between nodes
Every packet heard runs from its origin through the repeaters with a
position to this device; a packet sent is a ring. ui-core/PacketFlow.h
resolves them (UiCore::flow, MyMesh logRx/logTx -> Listener). ui-lvgl
draws them on the map's marker layer and repaints only their area while
they move; ui-new draws the last minute on the Nodes map ("Flow" in its
options). Setting: Map options > On the map > Packet flow, CLI map.flow.
Off by default. Sim-checked only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 12:50:43 +02:00
JakubandClaude Opus 5.5 120ddfc830 feat(route): trace per link, to the node or the last repeater, find where it stops; channel order re-sorts on entry
Core: PathEditor results are links (node k hearing k-1 and back); toNode()
off traces only the repeaters (a companion answers only with repeat on);
probe() traces to each repeater in turn after no reply; failures carry a
reason; an empty list saves "direct". PingEngine takes over a slot left past
its timeout. A kept route: the dropped heard path isn't announced to the app
nor bumps lastmod; an app update keeps the flag only if it leaves the route.
Marker boxes sized for every dot and name (overflow).

ui-lvgl Route: one line per node with out / back dB coloured by quality, tap
a hop to move / remove, tap the node to include it, Keep in the header, Find
where beside a no-reply status. ui-new Path: To node / Find break rows,
result alerts, cursor kept on its action.

Channels: ui-new re-sorts the list on entering it, cursor on the same channel.
Docs: Path and trace, Channel order. Sim hooks: open route, add channel,
open messages.

Checked in the browser sim (L2 + ui-new peer + repeater); not on hardware.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 11:20:55 +02:00
JakubandClaude Sonnet 5.5 24dd025086 feat(channels): Channel order setting - slots, newest message or name (#48)
Shared chanctl::order() builds the channel list for ui-new and the L2:
favourites first, then by ch_sort. New ch_sort pref at the end of NodePrefs,
Settings > Contacts row and contacts.channel.order CLI key.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 10:46:20 +02:00
JakubandClaude Sonnet 5.5 140ea7c008 feat(route): path editor with out-and-back trace and a kept route; map markers as one drawn layer
Core: PathEditor (UiCore::route) loads, edits, traces and saves the route to
a contact; MyMesh::sendTrace over an explicit route with per-hop SNRs,
setContactPath / setContactPinned. A route can be kept
(CONTACT_FLAG_ROUTE_PINNED, ContactInfo::flags bit 4): a path heard from the
node doesn't replace it and the last DM resend doesn't drop it.

ui-lvgl: Route screen (node detail), repeater picker by distance, picking
hops by tapping the nodes map (numbered badges, line, Undo / Done). The
map's markers are one drawn layer with hit-testing and name decluttering
instead of three objects per node.

ui-new: Path / trace view in the Nodes action menu; Add reuses the list
filtered to repeaters.

First cut: built for L2 LVGL, L1 OLED and L1 e-ink, tried on L2 only.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-13 10:18:05 +02:00
JakubandClaude Opus 5.5 c180814960 feat(ui): tab turn view slides in 140 ms, ahead of the bar's 220 ms glide
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:15:33 +02:00
JakubandClaude Opus 5.5 beb99878b1 feat(ui): tab bars glide on a tab turn, the view below slides as Home's pages do (OLED)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 23:02:12 +02:00
JakubandClaude Opus 5.5 4c1ebebcde fix(ui): lines and outlines follow the pixel scale on the 4.26" e-ink, opening a conversation no longer re-anchors on its second frame
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:53:59 +02:00
JakubandClaude Opus 5.5 b41d77fbb2 feat(eink): lettering clock on the portrait e-ink, 4.2" and 4.26" simulator builds in the release workflow
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:34:05 +02:00
JakubandClaude Opus 5.5 a7b1c3417b refactor(prefs): 2.0 settings layout -- fields in their sections, rc1 conversion and dead font flag gone
PREFS_VERSION 2: settings saved by 2.0-rc1..rc3 are not read, the device
starts from the defaults (v1.x /new_prefs is still imported as before).
The fields appended at the end during the rc cycle move into their
sections (BLE off, battery curve, text/icon size, message alert, advert
position precision, lock screen look). ch_scope_follow and its rc1
conversion and the unused use_lemon_font are removed. Stale comments in
NodePrefs.h and Trail.h fixed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:36:42 +02:00
JakubandClaude Opus 5.5 b9735b089e fix: missing returns, BIT macro clash, longer tile source URLs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:53:53 +02:00
JakubandClaude Opus 5.5 18f5627b2a fix: upstream security and robustness fixes (MACThenDecrypt alignment, CLI buffer, packet pool, raw data paths, ESP32 time after reset, Bosch sensor address)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:53:53 +02:00
JakubandClaude Opus 5.5 ec42a74ab6 perf: unused TinyUSB classes off on nRF52, SSD1306 sends only changed blocks, ESP32 loop yields when idle
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:30:46 +02:00
JakubandClaude Opus 5.5 2b9e013071 fix(l2): no remount while the card is a USB drive, vector packs locked across cores, time zone list, noise sweep restore
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:30:46 +02:00
JakubandClaude Opus 5.5 57db27512d fix(companion): pack and history files from the card checked, contact loops skip the reserved slots, small UI fixes
- L2 vector packs: a damaged count can't wrap the index size, and an
  entry pointing past the file is refused.
- L2 map share-target list: sized for 40 long channel names and 16
  favourites (it could overflow), off the stack.
- L2 SD history: a file with an unreadable header is set aside as .bad
  instead of written over; Delete message history takes those too.
- Contact lookups by key or hash start after the reserved anon slots (an
  empty one matched a 00 hop hash with a blank name); MessagesScreen uses
  contactctl::hopName().
- Nearby keeps its selection by public key: deleting a contact shifts
  the table.
- ui-new Live Share target cycle holds every channel and favourite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:31:35 +02:00
JakubandClaude Opus 5.5 4eee794a17 fix(companion): hashtag join trims like the app, prefs survive a downgrade, a sender named Me
- Joining #topic drops surrounding spaces and keeps the case, as
  meshcore-open's derivePskFromHashtag() does.
- /prefs written by a newer build (bigger NodePrefs, same version): the
  extra bytes are read through the CRC and skipped instead of resetting
  every setting.
- A channel post from someone named "Me" is filed as "\"Me\": ...", so
  the views don't take it for our own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:14:08 +02:00
JakubandClaude Opus 5.5 01a068be7d refactor(companion): shared shutdown steps, SD channel key by secret, fetch race, small UI fixes
- UITaskBase holds what both UIs' shutdown() and low-battery check share:
  the saves before the goodbye sound, the power-down (GPS through its
  provider) and the battery EMA and threshold.
- L2 SD archive: a channel's file is keyed by its secret only, so renaming
  keeps the history; old files are renamed once at boot.
- L2 fetch: abandoning a request and the task finishing it are one critical
  section (it could stay DONE for good); TileCache gets the read-side barrier.
- Text from a repeater or sensor no longer rings on the device (nothing to
  open); a settings switch reads any non-zero value as on; the message
  toast never cuts a letter in half; ui-new's GPS helpers ask UiCore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:08:31 +02:00
JakubandClaude Opus 5.5 28d8291e33 fix(companion): CLI NaN, APC on TX changes, tz-aware alarm, late ACKs, ping timeout and widths, TX limits
- set af / dutycycle / rxdelay reject nan.
- A TX power change from the app or CLI re-baselines APC.
- CMD_SET_RADIO_PARAMS stores repeat as 0/1.
- The alarm reschedules itself when the time zone changes.
- A late ACK for an earlier DM attempt marks it delivered.
- A new auto-advert interval counts from the last advert.
- Both UIs take the TX power range from radioctl, up to MAX_LORA_TX_POWER
  (30 dBm on the GAT562 30S).
- The ping timeout comes from the airtime; 3-byte path hash mode pings with
  4-byte trace hashes, and trace flags are right for width 4.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 18:00:49 +02:00
JakubandClaude Opus 5.5 cd294613ea fix(companion): scopes, room bot backlog, DM flood fallback, atomic trail saves
- Removing a scope moves the channels that used it to the default, not to
  unscoped.
- The room bot ignores posts older than 5 minutes: the backlog a room
  replays after login no longer gets answers.
- Adverts take the default scope from the scope list, as messages do; the
  legacy fields always mirror it, and CMD_SET_DEFAULT_FLOOD_SCOPE with a
  full list answers TABLE_FULL.
- The last DM resend drops the direct path and floods.
- /trail and /waypoints are written through a temp file.
- An admin login timeout keeps the saved password.
- History records read from the SD card are sanitised.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:54:38 +02:00
JakubandClaude Opus 5.5 fd45c2219b fix(gps): power saving put the receiver back to sleep before a new fix
MicroNMEA's valid flag survives a power cycle, so the duty cycle saw the
old fix right after waking the receiver and stopped it again a tick
later: with GPS power saving on the position never updated. begin() now
clears the parser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:48:58 +02:00
JakubandClaude Opus 5.5 bca926eee2 fix(serial): no 300 ms stall per frame with no USB host
With the phone not connected, every frame (each packet heard, each advert)
went to the USB port. With nobody holding it open the core either drops the
bytes or lets its buffer fill, and streamWriteUntil() then spun out its whole
timeout. Skip the write when the native USB Serial has no host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:07:18 +02:00
JakubandClaude Opus 5.5 7ad11b6f02 build(solo): drop the L2 bring-up and Arduino 2.0.17 envs
Neither is published or used any more: the LVGL firmware on Arduino-ESP32
3.x is the only L2 build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:41:39 +02:00
JakubandClaude Opus 5.5 010583b710 docs: rc3 release notes, the 4.26" panel in the hardware page and README
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v2.0-rc3
2026-10-11 21:36:53 +02:00
JakubandClaude Opus 5.5 b393732b90 refactor(companion): our MyMesh additions in their own headers
Contacts and rooms, the scope list, discovery and ping, APC and
screenshots move out of MyMesh.cpp to headers included at its bottom,
as MyMeshBot.h and MyMeshCli.h are, so upstream merges meet less of our
code. The feature matrix gains the 4.26" in its layout tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:26:59 +02:00
JakubandClaude Opus 5.5 4e95647c0d refactor(ui-lvgl): widgets, the virtual list, chats, nodes, thread and settings out of UITask.cpp
A pure move: each section now sits in its own header, included where its
code was, so the order of definitions is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:26:59 +02:00
JakubandClaude Opus 5.5 e896e6af60 refactor(ui-new): Home, splash, CardKB and the perf walk out of UITask.cpp
A pure move: each block now sits in its own header, included where its
code was, so the order of definitions is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 21:26:58 +02:00
JakubandClaude Opus 5.5 a5423d42c1 build(solo): the 4.26" panel as a fourth L1 e-ink env
WioTrackerL1Eink426_solo_dual extends eink_solo like the 4.2" build and
sets only what differs: the panel, rotation, the 9x15 at 2x with Text and
Icon size, bulk writes at 8 MHz, 250 contacts and a 32-message queue.
Replaces the full copy of the flags in solo/wio-tracker-l1-gdeq0426/.
Docs: advert precision, text and icon size, the 4.26" in the feature matrix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 10:52:17 +02:00
Jakub 1b318af15b Merge pull request #46 from pmow/feature/eink-ui-scale
GDEQ0426T82 4.26" panel (#42), bulk SPI writes (#43), Text size and Icon size for big panels

# Conflicts:
#	examples/companion_radio/DataStore.cpp
#	examples/companion_radio/NodePrefs.h
2026-10-11 10:41:29 +02:00
Jakub d749633b04 Merge pull request #44 from pmow/feature/advert-loc-precision
feat(companion): advert position precision (privacy)
2026-10-11 10:41:15 +02:00
JakubandClaude Opus 5.5 beef9edf5a fix(cli): keys pages counted as they are printed
A page break counted a space before every key, printing put none before
the first, so the skipped pages broke one key early and the next page
began with the previous page's last key.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 10:41:05 +02:00
pmowandClaude Opus 5.5 95a58a5532 feat(solo): GDEQ0426T82 in the 9x15 font at 2x
The 4.2" build's 9x15 font (EINK_LARGE_FONT=2) at 2x -- 18x30 cells,
~44 characters x 16 lines -- instead of the 6x9 at 4x, which goes blocky.
Compared side by side on the panel, as suggested in review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 17:10:06 -10:00
pmowandClaude Opus 5.5 13531dd2ce refactor(eink): Text size and Icon size as schema settings, on opt-in builds only
Review follow-up:

- The rows exist only where the build asks for them: Text size with
  EINK_FONT_SCALE, Icon size with STATUS_ICON_SCALE. The stock 2.13", the
  portrait builds and the L2 don't get them -- their screens are laid out
  for one cell size. The text override also applies in landscape only.
- Stored in NodePrefs (ui_text_scale, ui_icon_scale) instead of a
  /ui_scale file, as rows in the schema's Display section: the usual row,
  save path and factory reset, and console keys display.text.size /
  display.icon.size. The hand-written Settings rows and the load/save code
  are gone; UITask::applyUiScale() applies the prefs at boot and on change
  (applyDisplayPrefs). On opt-in builds ui_text_scale starts at the
  build's EINK_FONT_SCALE (DataStore sanitize), so the row shows the scale
  in use.
- EINK_FONT_SCALE, when set, now scales whichever landscape font the build
  picks (the 6x9, or the EINK_LARGE_FONT one); unset, it is stock as before.
- setUiScale() skips the re-layout and full redraw when nothing changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:36:39 -10:00
pmowandClaude Opus 5.5 a25df3ceec feat(companion): advert position precision (privacy)
Settings > Privacy > Precision: Exact / ~100 m / ~500 m / ~1 km, beside
"Position in adverts", which stays the on/off. With the position shared,
it is snapped to a fixed grid (0.0009 / 0.0045 / 0.009 degrees) rather
than jittered, so repeated adverts from one spot send the same value and
can't be averaged back to the exact fix.

A schema row (NodePrefs::advert_loc_prec), so both UIs show it, factory
reset clears it and the console has it as advert.loc.precision.

Every self-advert -- manual, flood, auto, the phone app's and contact
export -- now goes through MyMesh::createOwnAdvert(), so the precision
applies everywhere.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:22:16 -10:00
pmow c06b394144 Merge dev into feature/eink-ui-scale 2026-10-10 16:19:17 -10:00
pmow ef7ef4b8d5 Merge #43 (GxEPD2 version comment) into feature/eink-ui-scale 2026-10-10 16:19:17 -10:00
pmow beae8de734 docs(eink): name the GxEPD2 version GxEPD2_FastWrite.h copies from
setRamArea() and fastWrite() follow GxEPD2 1.6.2's private
_setPartialRamArea() and _writeImage() for the GDEQ0426T82; say so, so
whoever bumps the library knows to re-check them.
2026-10-10 16:14:18 -10:00
JakubandGitHub 2820c36b1c Merge pull request #45 from pmow/fix/cardkb-during-refresh
fix(ui-new): keep CardKB key presses during an e-ink refresh
2026-10-10 10:20:03 +02:00
JakubandClaude Opus 5.5 c5bb4752d0 feat: per-contact actions, device settings, a companion CLI and your contact's QR code
- Nodes: telemetry permissions per contact, reset path, share nearby
  (L1 options menu; L2 node card with "Can ask for" switches)
- Settings > Privacy: fixed position (typed in, from a waypoint, cleared)
  and the Bluetooth PIN; Settings > System: factory reset, asked twice
- Companion CLI (CMD_RUN_CLI_COMMAND 66 / RESP_CODE_CLI_REPLY 29, as
  upstream; FIRMWARE_VER_CODE 14): upstream's command names plus a key for
  every schema setting (get / set / keys)
- Screenshots move to 0x7E; tools/screenshot.py falls back to 66 / 29
- Your contact as a QR code (meshcore://contact/add): Status > System on
  ui-new, Settings > About on the L2; Nayuki's qrcodegen made header-only

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:59:35 +02:00
JakubandClaude Opus 5.5 6fba3dfca7 feat: app-only settings on the device: privacy, adding contacts, advanced radio
- Settings schema gains Privacy (position in adverts, who can ask for
  status / location / sensors), Adding contacts (all or by type, max
  hops, replace oldest) and Advanced radio (path hash size, double ACK,
  listen before talk, interference threshold, RX boost, RX delay,
  airtime factor); both UIs build their rows from it
- Auto-advert carries position only when Position in adverts is on
- ui-new accordion holds 16 sections and 128 rows
- docs: settings, tools, feature matrix

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:47:03 +02:00
JakubandClaude Opus 5.5 a0a76fbc60 fix(watch13): build with -Os like the other nRF52 solo boards
The Watch13 env still compiled with -Ofast and had run out of flash
after the map, calendar and QR commits. -Os brings it to 70.7%.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 00:47:03 +02:00
pmowandClaude Opus 5.5 2c1e1fa930 feat(eink): Text size and Icon size settings for big panels
On an 800x480 panel the doubled 6x9 font and the status bar's icons are
tiny. Two opt-in build flags, each also a setting under Settings > Display:

- EINK_FONT_SCALE=<n>: the landscape font's pixel multiplier (stock 2).
  Settings > Display > Text size (1x-5x) overrides it at run time
  (DisplayDriver::setUiScale -> EinkGfxDisplay re-lays out).
- STATUS_ICON_SCALE=<n>: Home's status icons, battery and page-icon row
  drawn at n x their pixel grid, the bar growing to fit. 0 = Auto, 1.5x
  the text's pixel scale. Settings > Display > Icon size (Auto, 1x-8x).

Both live in their own /ui_scale file, so NodePrefs is untouched. Icon size
appears only where STATUS_ICON_SCALE is set; Text size appears on every
e-ink build with the full-refresh setting, and builds that set neither
flag draw as before until it is changed. The GDEQ0426T82 env defaults to
4x text with Auto icons.

Tested in the native sim at 800x480.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KxAZVAbhhYr18Dd4guTQM1
2026-10-09 11:57:29 -10:00