Commit Graph
396 Commits
Author SHA1 Message Date
Kaj SchittecatandClaude Opus 4.8 f7a550685c lua: SD adoption migrates /apps too (mkdir the FAT parent so the copies succeed)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:07:24 +02:00
Kaj SchittecatandClaude Opus 4.8 1a1fc0f260 lua: bare .lua files on the card are apps — no manifest needed
Drop myapp.lua into /meshcomod/apps/ on the SD (any reader, the Files
app, USB) and it appears in the drawer named after the file (ver 'dev').
Manifests stay the store's install format; the second scan pass only
picks up ids no manifest claimed. macOS ._* AppleDouble junk skipped.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 13:03:14 +02:00
Kaj SchittecatandClaude Opus 4.8 7e6ff56a3f lua: rebuild the app drawer when the Store closes over it (fresh installs appear immediately)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:59:30 +02:00
Kaj SchittecatandClaude Opus 4.8 2a60138e16 lua: Snake is store-only on Lua boards + long-press-to-remove on installed tiles
The built-in Snake tile and embedded copy are gone where the host exists,
install it from the catalog like any app (non-Lua boards keep the native
game). Installed app tiles gain a long-press remove with a confirm sheet;
the post-long-press release click is swallowed so the app does not launch
under it. Store 'Remove' and the tile path share one removal helper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:57:30 +02:00
Kaj SchittecatandClaude Opus 4.8 ed22bd071c lua: store page fixes — layer_top stacking (drawer covered it) + pre-layout width read
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:50:38 +02:00
Kaj SchittecatandClaude Opus 4.8 6b29714f60 lua: Phase 2 — App Store page, catalog installs, drawer integration, hide toggles
The Store (new drawer tile) lists the VPS catalog (apps.json on
firmware.wadamesh.com, fetched on the net worker like the version check),
installs/updates/removes Lua apps (two files under <root>/apps/, .sav kept
across reinstalls), shows sideloaded apps, and hosts show/hide switches
for the built-in drawer tiles (app_hide bitmask, prefs v46 appended under
the schema's trailing assert). Installed apps appear as drawer tiles and
launch through the host. Catalog + snake 1.0 staged under out/firmware/apps
and live on the VPS (nginx /apps locations added).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:39:35 +02:00
Kaj SchittecatandClaude Opus 4.8 322e4dd6f2 lua: Phase 1 — app host + wada.* v1 + Snake in Lua (hardware-verified)
LuaAppHost: one sandboxed app at a time as an AppPage overlay, every
callback under a 100k-instruction budget + traceback pcall (an app error
is a toast and a clean close, never a reset — proven live when the first
Snake build errored: 4 contained retries, zero leak). Bindings: wada.ui
canvas/label/button + theme colors, hardware-swipe/trackball/touch input,
timer, sys (millis/toast/board/random), per-app KV store under the data
root. Snake rewritten in Lua as the embedded reference app; the drawer
launches it via the host and prefers a user-editable /apps/snake.lua.
CAP_LUA_APPS defaults on for all touch boards. T-Deck: 85.1% flash
(host layer = 13 KB over the VM), app opens at 19 KB PSRAM.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:23:11 +02:00
Kaj SchittecatandClaude Opus 4.8 f2067848a7 lua: Phase 0 — vendor Lua 5.4.7 + PSRAM-capped sandbox spike (GO: +96KB flash, 7.5KB state)
Vendored 5.4.7 core+stdlib under lib/lua (mains excluded), LUA_32BITS
baked into luaconf.h so the VM and embedders share one ABI. LuaHost spike
behind WADA_LUA_SPIKE: PSRAM-only allocator with a hard 256KB cap,
io/os-free sandbox, instruction-budget hook. Measured on the T-Deck:
flash +96KB, state+libs 7.5KB/2ms, hostile while-true contained in 30ms,
zero leak. Inert (byte-identical build) when the flag is off.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 12:00:49 +02:00
Kaj SchittecatandClaude Opus 4.8 2fd578515d touch: P4 backups write to the LittleFS store, not unmounted FFat (#231)
backupInternalFs() still returned FFat on the T-Display P4, but the hot
store moved to LittleFS('storage') at beta_54 and FFat is never mounted
since - every profile export and backup failed at open with 'can't open
file'. The list and restore paths share the helper, so all three heal.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 10:41:02 +02:00
Kaj SchittecatandClaude Opus 4.8 a44d2a2193 touch: repair the #227 Hungarian merge - restore LANG_RO, remap stored ui_lang, dedupe one row
The PR inserted LANG_HU at slot 1 (shifting every stored language choice)
and dropped LANG_RO from the enum while the table still carries all 14
columns, so it did not compile as-is. Romanian is restored to the enum in
the table's column order, a one-time v45 remap keeps every existing user's
language selection, one row had its Hungarian cell pasted twice, and the
enum gained an append-only warning.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 10:30:48 +02:00
Kaj Schittecat 66a7714e90 Merge pull request #227 from pisti87/main 2026-08-04 10:26:22 +02:00
Kaj SchittecatandClaude Opus 4.8 c49fac407c touch: auto-retry is opt-in (default OFF) on top of the #230 schema repair
Per user feedback on beta_57: the retry default is the user's choice to
make. Applies to the v45 migration line, the fresh-install default, and
the pre-UI mesh state.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 10:24:25 +02:00
Kaj Schittecat 10ed6a6e80 Merge pull request #230 from PixPMusic/pixpmusic/prefs-schema-repair 2026-08-04 10:23:59 +02:00
Kaj Schittecat cb17ee80a9 Revert "touch: repair the beta_57 prefs layout shift + auto-retry now opt-in (v45)"
This reverts commit b0c31c9105.
2026-08-04 10:21:41 +02:00
Kaj SchittecatandClaude Opus 4.8 ed2b2cb135 touch: WADAMESH lock-screen wallpaper (#228)
The default lock wallpaper had MESHCOMOD baked into the image pixels
(both the rendered RGB565 embed and the SPIFFS-seeded JPEG) - the beta_56
branding fix only changed the animation text drawn over it. Regenerated
both assets with the WADAMESH wordmark and brand-teal padlock; the JPEG's
size change makes the SPIFFS seeder replace the old copy on next boot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 10:11:27 +02:00
Kaj SchittecatandClaude Opus 4.8 b0c31c9105 touch: repair the beta_57 prefs layout shift + auto-retry now opt-in (v45)
beta_57 inserted retry_echo MID-struct (between rx_queue and web_mirror)
instead of at the blob tail. The stored cfg is a raw memcpy, so on upgrade
every later u8 shifted one byte: remote_mode inherited remote_landscape's
force-flipped 1 (v37) - every upgraded device booted into remote mode -
map_tile_debug inherited hist_sync_after's 2 (debug overlay on), and
hist_sync_after fell to 0 (blocking chat-flush fallback disabled).

v45: retry_echo moved to the true tail, a one-time repair resets the
shifted run on v44 blobs (originals unrecoverable - beta_57 re-flushed
over them), and auto-retry is opt-in now (default OFF) per user feedback.
Struct gains a loud append-only warning. Layout verified with a host-side
byte-level test of all three upgrade paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-04 08:33:51 +02:00
István def866d07b Merge branch 'main' into pisti87-hungarian-lang 2026-08-04 07:43:02 +02:00
Pixel Perfect 65f25334c4 fix(prefs): repair beta 57 config migration
Beta 57 inserted retry_echo into the middle of the packed TouchCfg blob, shifting the remote-mode and later fields during migration. Define a v45 layout with retry_echo appended at the true tail and recover ambiguous v44 suffix bytes to safe defaults while preserving the stable prefix. Add a host regression test for v43, broken v44, and v45 blobs.

Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-03 19:01:35 -07:00
Kaj SchittecatandClaude Opus 4.8 169971205d touch: run the SD format + paste workers on every board that offers them (#172)
The Format button (and its busy overlay) is compiled for T-Deck, M9 and
V4-R8, and Copy/Paste for every Files-app board, but both deferred workers
in UITask::loop were gated T-Deck-only. Elsewhere the tap set a pending
counter nothing consumed: the notice stayed up forever and the format
latch blocked SD remounting until reboot. Widen the format worker to the
button's gate (via the per-board sdSharedSPI accessor), ungate paste.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 17:02:14 +02:00
Kaj SchittecatandClaude Opus 4.8 f4a6c1b3ad touch: recolor-safe node names in Discover feed + msg-info trace (#223)
A repeater name with an emoji (multi-byte UTF-8 cut at a byte cap) or a
literal '#' desynced the LVGL recolor runs in the Discover feed, visually
killing every row after it; same class in the message-info repeat list.
Names are now UTF-8-boundary-cleaned and '#'-escaped at both sites, and
copyUtf8ReplacingMissingGlyphs no longer emits a split glyph at its cap.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-03 16:52:34 +02:00
István 4b752919a4 Update i18n.cpp 2026-08-03 16:32:50 +02:00
István 402585d0b5 Update i18n.cpp 2026-08-03 16:25:52 +02:00
Kaj Schittecat e1aceec8a8 Merge pull request #212 from PixPMusic/pixpmusic/sd-prefs-concurrency 2026-08-03 15:52:04 +02:00
Kaj Schittecat 829278c9a2 Merge pull request #213 from PixPMusic/pixpmusic/storage-wdt-state 2026-08-03 15:51:55 +02:00
Kaj Schittecat c64a6eae49 Merge pull request #211 from PixPMusic/pixpmusic/datastore-pref-rename 2026-08-03 15:45:48 +02:00
Kaj SchittecatandClaude Opus 4.8 78fed3a09d touch: Radio & Mesh toggle for the #207 auto-retry (default ON, opt-out)
'Retry sends until heard' switch under Radio & Mesh gates mikecarper's retry
train (#207): OFF stops new retry trains (an in-flight one finishes its
schedule), applied live and persisted (cfg v44 retry_echo, default ON).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 15:23:19 +02:00
István 568001e1db feat(lang): add Hungarian language v0.3 2026-08-03 11:19:04 +02:00
Pixel Perfect afd41c393f fix(storage): make the heavy-WDT depth counter atomic
_wdtHeavyDepth() is a plain int, but WdtHeavyGuard is taken from both the
UI/loop task and the core-1 history worker (histFlushTaskFn ->
uiSegRunArmedJob -> uiSegAppendRecords/uiSegCompactWrite, each of which holds
one). Both run at priority 1 on core 1, so ordinary tick round-robin can
preempt between the load and the store of d++ / --d.

That race predates this PR, but this PR makes it likely rather than
theoretical: the new guard in rebootDevice() is constructed immediately
before uiHistWaitWorkerIdle(), a deliberate wait of up to 9 s on the very
worker that also takes the guard. Interleave the two and either

  - the depth strands above zero, so enableCore0WDT() is never called again
    and IDLE0 stays unsubscribed from the task watchdog for the session, or
  - the depth drops to zero while a guard is still held, re-arming the
    watchdog during the flash burst it exists to cover -- which panics
    mid-save and loses exactly the chat history rebootDevice() runs to
    persist.

Use std::atomic with an acq_rel fetch_add and a compare-exchange decrement.
The CAS preserves the original `d > 0` underflow guard, which still matters:
doFactoryReset() calls wdtHeavyBegin() with no matching end because it
reboots, so the counter can legitimately stay elevated and an unbalanced end
must not drive it negative.

Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-02 13:15:06 -07:00
István b7d55db5e6 feat(lang): add Hungarian language v0.2
v0.1 6-303 ok
v0.2 305-386 ok
2026-08-02 21:52:52 +02:00
István 0d5b1ec9c6 add lang: hu
hungary lang added 0.1 1-303. ok
2026-08-02 19:09:20 +02:00
Pixel Perfect 4418b1f598 fix(prefs): avoid heap churn on cached reads
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 23:57:39 -07:00
Pixel Perfect 42a545a570 fix(storage): keep IDF watchdog guards nontrivial
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 22:34:41 -07:00
Pixel Perfect 7f4776e20d fix(storage): let clean preference flushes succeed
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 22:03:33 -07:00
Pixel Perfect a92afa191c fix(storage): gate loop watchdog APIs in IDF apps
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 21:59:17 -07:00
Pixel Perfect 8252e43b32 fix(storage): deduplicate concurrent preference loads
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 21:20:48 -07:00
Pixel Perfect 1e6a6b4b35 fix(storage): inspect the Arduino loop task watchdog
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 21:20:48 -07:00
Pixel Perfect 958ace84aa fix(storage): make file-backed preferences concurrency-safe
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 20:37:01 -07:00
Pixel Perfect 9202ad0a10 fix(storage): preserve loop watchdog state
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 20:33:06 -07:00
Pixel Perfect 603217312e fix(storage): commit rooted preference updates
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 20:33:04 -07:00
mikecarper 04d5f33575 Retry messages until an echo is heard 2026-08-01 17:13:03 -07:00
Kaj SchittecatandClaude Opus 4.8 bcc084820c touch: radio presets set a REAL duty limit — airtime factor was 10x off (#161)
MeshCore's airtime_factor is the Dispatcher's TX pacing multiplier: duty =
1/(1+af), so a 10% duty limit needs af = 9. The presets wrote af = pct/100
(0.10), which configured every preset user's radio to ~91% duty -- the Home
meter's 'always 91%' was truthfully reporting the misconfiguration, on every
region preset including UK/EU.

- applyMeshRadioPresetFields converts duty% -> factor correctly (clamped to
  the core's 0..9).
- findMatchingMeshRadioPreset accepts both the correct and the old buggy value
  so previously-configured devices still show their preset in the dropdown.
- healPresetAirtimeFactor (run once at UI begin) rewrites the factor for
  devices whose params exactly match a preset and whose stored factor matches
  the OLD buggy write -- the exact-match requirement is the guard against
  touching deliberate user-set values.

NOTE for the web client: Meshcomod-client/shared/radio_presets.ts documents
the same pct/100 convention and needs the matching fix.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 12:23:18 +02:00
Kaj SchittecatandClaude Opus 4.8 a2548c39ab touch: T-Pager gets the full store-on-SD machinery (#193)
The pager's SD support shipped in pieces (mount ladder with XL9555 card-detect,
tile-cache fallback, shared TFT_eSPI SPIClass) but CAP_SD/CAP_FILESYSTEM were
never flipped from the pre-wiring 0, so the Files app gates and the whole
'Store data on SD' machinery stayed compiled out -- an inserted, mounted,
browsable card that nothing would store to. Flipped the caps, extended the
boot storage selection + SPIFFS->SD migration + SdNvsPrefs routing gates to
TLORA_PAGER, and exported tloraPagerSharedSPI() from the variant so main.cpp
can mount the card at boot on the shared bus like the T-Deck.

Both pager envs + T-Deck + V4 + R8 build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 12:19:46 +02:00
Kaj SchittecatandClaude Opus 4.8 badad25305 touch: issue batch — unlock branding (#165), Discover row overflow (#191), scope in details (#157)
- #165: the animated post-unlock overlay still said MESHCOMOD; now WADAMESH.
- #191: Discover app rows cap the name and use single-letter node types so the
  trailing last-heard age always fits the line.
- #157: the Info popup only read the transport scope for FLOOD messages, so a
  region-scoped DIRECT message showed no scope; and senders that carry the
  region in transport_codes[1] with codes[0]=0 showed Scope 0000. The scope is
  now read for any RX and falls back to codes[1] when codes[0] is zero.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 12:13:08 +02:00
Kaj SchittecatandClaude Opus 4.8 51617b404e touch: SD mount ladders renegotiate the clock upward after a slow-rung init (#194)
A card whose power-up handshake only completed at 400 kHz kept 400 kHz as its
SESSION clock — SD.begin's frequency is the operating clock, and neither the
boot ladder (main.cpp) nor the runtime ladder (fmSdTryMount) ever raised it
after a slow success. With the SD as the T-Deck's primary store that meant
loading contacts + history at ~25 KB/s: the reported ~3-minute boot, f_getfree
timeouts making an inserted card show as 0 KB/empty in the file manager, and
backups wedging. Launcher installs hit it most (the Launcher's own SD use
leaves the card needing the slow wake path more often).

Standard SD bring-up is init-slow-then-raise: after any sub-4MHz success both
ladders now re-begin at 4 MHz, falling back to the clock that just worked if
the fast re-begin fails. A healthy card is unaffected (mounts at 4 MHz on the
first rung). T-Deck + V4-R8 + M9 (the shared-SPI SD boards) build.

Likely also behind the long-standing Launcher-mode weirdness cluster together
with the torn-prefs fix (#195/#196): slow-clock sessions made every write
window enormous.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 11:36:24 +02:00
Kaj Schittecat 67b863d93e Merge branch 'main' of https://github.com/ALLFATHER-BV/wadamesh 2026-08-01 11:29:52 +02:00
Kaj 44a4a354b0 Merge pull request #197 from PixPMusic/pixpmusic/pager-ui-size
feat(touch): add T-Pager UI size presets
2026-08-01 11:29:50 +02:00
Kaj Schittecat a3b535237e Merge branch 'main' of https://github.com/ALLFATHER-BV/wadamesh 2026-08-01 11:18:54 +02:00
Pixel Perfect 05f4ba6542 feat(touch): add T-Pager UI size presets
Signed-off-by: Pixel Perfect <me@pixp.cc>
2026-08-01 02:14:24 -07:00
Kaj SchittecatandClaude Opus 4.8 c0d702a8a7 touch: control-centre GPS tile long-press opens the GPS page, not Radio
Stale CAT_RADIO from before the settings reorg gave GPS its own category —
every other tile already pointed at its own page. All boards.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-01 10:15:26 +02:00
István 2270c5d2cc Update i18n.cpp 2026-08-01 05:34:55 +02:00