Commit Graph
10 Commits
Author SHA1 Message Date
twislaandClaude Opus 5.5 7fe8b3d22a Help: Fn+h lists the keys of the screen you're on, and no screen names its keys any more (#69)
CI / build (pull_request) Successful in 7m22s
Site / build (pull_request) Successful in 14s
Fn+h on any screen, text fields included, and ? outside Text Entry, open a
panel over the content area: the screen's own keys, then the ones that work
everywhere. Every App declares its keys for the state it is in (pages,
viewers, dialogs and text fields answer for themselves); the App manager
opens the panel and takes every key while it is open.

About 30 hint lines are gone, from every App. What stays on a screen is
state. The first-start Setup keeps its hints and teaches the key; a device
set up before gets one Toast, once. The guide and the FAQ open with it.
`key help` over the consoles.

476 host tests (8 new). Checked on the device with key help and screenshots:
the Launcher, all nine Apps and several of their states. 8.5 KB of flash and
40 bytes of static RAM. Decisions Q196 to Q203 in docs/milestones/U1.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-07 01:29:51 +02:00
twislaandClaude Opus 5.5 c68741cc46 One firmware: the Debug Console in every build, off until switched on, with the device's own token
CI / build (pull_request) Successful in 7m20s
Site / build (pull_request) Successful in 9s
There is no Debug Build any more (ADR 0010, issue #68, Q188 to Q195). The
console and the test commands are compiled into every firmware. It listens
only while Settings > Debug Console is on, which isn't the default; off,
neither its task nor its 4 KB ring exists. The token is made by the device
and shown on that page; a client proves it knows it by answering a challenge
with an HMAC, so it never crosses the network, and five wrong answers close
the console for a minute. DBG in the Status Bar while it listens.

Over USB serial only: debug on, debug token <value>, debug token new.
scripts/flash.sh --debug uses them to set a device up with the developer's
token. scripts/rdbg.py takes the token from -t, $RORO_DEBUG_TOKEN or the
file, answers the challenge, and fetches a release's ELF to decode a crash.

Gone: the cardputer-adv-debug environment, RORO_DEBUG, the +debug version,
scripts/debug_flags.py, update install ... force, and the rule that a Debug
Build doesn't install releases. Old clients and old firmwares don't talk to
each other.

Against the builds it replaces: 30 KB more flash and 88 bytes more static
RAM than the release, 4 KB less RAM than the Debug Build. 468 host tests.
Checked on the device: off by default, login, the pause after wrong tokens,
Safe Mode with the console, the setting surviving an update, debug off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-06 22:59:35 +02:00
twislaandClaude Opus 5.5 b1de0f8804 M3 step 5: Sweep, the band's signal strength as bars and a waterfall
Tab in the LoRa Scanner sweeps 863-870 MHz in 100 kHz steps (the
strongest of three RSSI readings at each, at 125 kHz), shown as bars with
peak hold over a waterfall, the Sniffer's frequency marked (Q98). The
Sweep pauses the Sniffer and keeps its packets; Tab resumes it (Q99).
Status Bar: SW. The floor, top and peaks are host-tested; `lora sweep
on|off|dump` prints them on the console.

At the desk: about 607 ms a pass, a flat floor at -100 to -102 dBm
(15 dB above the chip's own) and a steady carrier at 863.2 MHz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-05 20:28:46 +02:00
twislaandClaude Opus 5.5 2fce79aebd M3 step 4: the LoRa Scanner App, Sniffer and Captures
The Sniffer lists packets newest first (time, RSSI, SNR, and for
Meshtastic the sender, receiver and hops), with the clear header and a
hex dump on Enter (Q96); `p` picks an EU868 preset, kept in Settings
(Q95). `c` starts a Capture: pcap with LoRaTap in /captures/lora, its own
Clean-up category, recorded by a small Service so it carries on with the
App closed (Q97, Q100). The Status Bar shows L while listening, bright on
each packet, and CAP while capturing (Q101). StorageService gains raw
appends for binary files. Debug Builds get `lora inject` to test all of
this with no transmitter in range: a Capture made on the device reads
back in TShark field for field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-05 20:14:58 +02:00
twislaandClaude Opus 5.5 d7952612dd M2 step 6: Tracks, recorded to GPX in the background
`r` in the GNSS App (or `gnss track start|stop`) records a Track to
/gnss/tracks/YYYYMMDD-HHMMSS.gpx: a point every 5 s once moved 5 m
(lib/gnss/track, 7 tests: haversine, the rule, GPX text, the file name).
It keeps recording with the App closed, shows REC in the Status Bar, and
announces start and stop with a Toast. It needs a card and the time;
switching GNSS off stops it. Tracks are written like Captures: past 90 %
card usage, until full. Storage Clean-up gets a GNSS tracks category.

A Track cut short by a reset or power loss has no GPX footer; the GNSS
Service closes such files at the next boot.

Verified on the device: a recorded Track and one interrupted by a reset
both parse as GPX 1.1 on the PC.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-04 22:46:57 +02:00
twislaandClaude Opus 5.5 d408bada07 M2 step 4: GNSS mark in the Status Bar; the clock follows the Fix
Q61: a muted G while searching (or the receiver is silent), G with a 2D
Fix, G and the satellite count with a 3D Fix; nothing when GNSS is off.
Verified on the device by a window: 3D Fix, 9 of 11 satellites used
(GPS, GLONASS, BeiDou), HDOP 1.3, Status Bar "G9", and "gnss: clock set".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-04 22:29:20 +02:00
twislaandClaude Opus 5.5 74a341418e M1 step 4b: IRC Service on the device; 8-bit frame buffer
- IrcService: networking on its own task, TLS with the built-in CA
  bundle (or trust-on-first-use pinning when self-signed is allowed),
  plain TCP when TLS is off; connects only while Wi-Fi is Connected,
  marks pauses for Monitoring, reconnects with backoff, pings a quiet
  server, writes Logs, raises Notifications for Mentions
- Session: forget /quit once disconnected (it was handled every loop);
  the server Buffer never counts as unread (MOTD showed as [4])
- Status Bar: unread count
- Frame buffer 16 -> 8-bit colour (M1 Q46): min free heap with IRC on
  TLS went from 51 KB to 79 KB
- Serial: irc start / say / dump

Verified on the device against irc.libera.chat:6697: certificate
checked, joined #roro9stack-test, sent a message, quit cleanly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-02 15:10:03 +02:00
twislaandClaude Opus 5.5 1a0baf4ac7 M1 step 2: Wi-Fi Service, Saved Networks, NTP, Settings page
- lib/wifi (host-tested): SavedNetworks (up to 8, validated, hidden
  flag, persisted) and WifiController (joins the strongest Saved
  Network, tries hidden ones in turn, backoff 10/30/60 s, connect
  timeout, Monitoring override, radio off without Saved Networks)
- WifiService carries out the controller's actions, sets the EU
  country code, and syncs the Clock over SNTP without touching the TZ
- Wi-Fi On/Off setting; Settings > Wi-Fi page: status, add from a scan
  or a hidden network, forget
- Status Bar: W + signal bars, W? while searching, MON while monitoring
- Serial: wifi add / wifi status (replaces the step 1 heap probe)

Verified on the device: joins the test network ~5 s after boot, clock
set over NTP, ~129 KB free heap while connected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-02 14:46:07 +02:00
twislaandClaude Opus 5.5 51698a8011 M0 step 7: Settings, About, Storage, first-boot setup
- lib/apps_model (host-tested): SettingsMenu (rows, readable values,
  choices, validation messages) and SetupWizard (names, Region
  confirmation, timezone; saves only when finished)
- AppManager: modal Apps that Home/Back can't leave (setup wizard)
- SettingsApp: all settings plus Storage (usage, erase SD behind a
  dialog) and About (version, node id, battery, memory, uptime) pages,
  replacing the temporary Diagnostics App
- SetupApp: first-boot wizard, opened modally until SetupDone
- Node id and default names derived from the MAC like Meshtastic
- Widget demo is now hidden (About, then w)
- lib_ldf_mode = deep+ so libraries see each other's headers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-02 13:47:03 +02:00
twislaandClaude Opus 5.5 879cb0d0b6 Add widget kit, input layer with Compose Key, Launcher and demo apps
Steps 5 and 6 of M0.
- lib/ui (host-tested): ListModel, LineEditor (UTF-8, byte-limited),
  wrapText, ToastQueue, DialogModel
- lib/input (host-tested): KeyMapper turns keyboard state into logical
  keys (Fn arrows, ` Back, Fn+` Home) and composes accents with opt
- src/ui: off-screen 16-bit frame pushed in one transfer (fixes the
  flicker), Status Bar, list, text, line editor, dialog, Toast widgets,
  Notifier (Toast + beep + LED), vendored public-domain Latin-1 fonts
- Apps: minimal Launcher, Widget demo, Diagnostics (SD erase now
  behind a confirmation dialog)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
2026-10-02 10:35:48 +02:00