Commit Graph
57 Commits
Author SHA1 Message Date
liquidraver f9d01cf33a upstream sync and gps stuff 2026-10-02 23:10:09 +02:00
liquidraver 2e0f765036 vanilla dev sync 2026-09-27 16:33:58 +02:00
liquidraver d5bd805710 peripherals & power: GPS fixes, poweroff/pwrmgt, upstream SensorManager telemetry
- gps: servers honour gps_enabled at boot (was lost on reboot; zc.gps_set
  upgrades older prefs to on once); sleep lock only while acquiring;
  gps off works on boards without a power line (UART sleep); UI toggles
  and fixes handled on the main thread; configure only after a good init;
  observer parks its GPS; one interval clamp (clampGpsInterval); one
  nav-mode knob (room servers on Air530Z now stationary); GNSS UARTE from DT
- gps: split into ZephyrGPSManager / gps_power / gps_module_cfg
  (+gps_internal.h); dead driver branches, gps_get_diag, sats_* removed
- clock: ZephyrRTCClock writes the hardware RTC itself (clkreboot now
  resets it); MESH_EVENT_RTC_SAVE gone
- power: one power-off path (zephcore_power_off, ZephyrBoard::powerOff),
  poweroff/shutdown CLI, get pwrmgt.*, crash record kept across reboot,
  battery reading cached 10 s, fuel gauge on the current API
- telemetry: upstream SensorManager + CayenneLPP (rounded to nearest),
  one builder for all roles; per-sensor channels, MCU temp always,
  guest gating and inverse mask on servers; sensor list/get/set work;
  BME280/BMP280 also probed at 0x77
- CLI: gps in upstream's form, get gps detail, gps sync
2026-09-25 17:56:34 +02:00
liquidraver 38f815a0a1 server roles, event loops, companion transports, storage and prefs.json
Server roles (slice 7)
- CommonCLI split into upstream's shape; region CLI moved into CommonCLI;
  ClientACL, RegionMap, TransportKeyStore and both server meshes in
  upstream shape over an Arduino compat shim (helpers/compat: Arduino.h,
  Stream/Print, Serial, SHA256, FILESYSTEM/File over Zephyr fs)
- room server processAck port; `get acl` prints as upstream
- room: default name Room-XXXX, display/input rotation, live radio UI refresh

Event loops (slice 7b)
- repeater and room server share server_main_common with a ServerRole
  descriptor; shared event bits in src/mesh_events.h
- room server deadline-driven (idle wakes 2.2/s -> 0.08/s); companion
  loop() runs on housekeeping (closes the lazy contact-flush gap)
- `get loop.wakes` in debug builds (CONFIG_ZEPHCORE_LOOP_WAKE_STATS)

Companion transports and WiFi (slice 8)
- upstream MultiSerialInterface: BLE, USB/UART and TCP are each a
  BaseSerialInterface, every connected transport gets every frame;
  CompanionSerial holds a lossless reply; shared frame_txq for BLE/TCP
- SerialCompanionTransport and LinuxTCPTransport replaced by
  TcpCompanionTransport; ZephyrBLE split (gatt layout, DFU)
- WiFi companion (upstream wifi.ssid/pwd/enabled CLI, TCP port 5000) on
  boards declaring `capabilities: wifi` in zephcore.yml: the PSRAM
  ESP32-S3 boards, plus Heltec V3 (140 contacts), Wireless Tracker (130)
  and both C6 boards (280); ESP32-S3 without PSRAM gets bounded WiFi
  buffers and a measured 72 KB heap; PSRAM boards' internal heap 72 KB
- TCP queues: own depth (ZEPHCORE_TCP_QUEUE_SIZE=8), RX waits instead
  of dropping
- RAM: companion ClientACL dropped; main/BT-TX/TCP stacks sized from
  measured peaks (-7 KB nRF companions, -9 KB ESP32 companions)
- ESP32 WiFi stopped working under ~200 frames/s unicast. Fixed by:
  patches/zephyr/0017 never block the WiFi task in the RX callback;
  patches/zephyr/0018 lock shared_multi_heap (heap corruption with the
  WiFi heap in PSRAM); patches/modules/hal_espressif/0001 backport of
  hal_espressif af97fb02df (PSRAM realloc)

Storage and prefs (slice 9)
- prefs are now prefs.json through upstream's ConfigSerializer (ported
  verbatim), with upstream's key names for shared fields and ZephCore's
  own under "zc"; on first boot the binary new_prefs / repeater prefs is
  migrated and kept, so a downgrade still boots with the old settings
- helpers/PrefsCodec: both legacy binary layouts (companion 272 B,
  server 311 B) as Zephyr-free codecs; sanitizeNodePrefs is the only
  validator
- fix: server prefs could be replaced by a truncated file when a write
  failed; identity, prefs and channel writes go through one checked
  atomic replace (ZephyrFsUtil)
- fix: a corrupt cad_auto byte turned adaptive CAD off instead of the
  default on
- fix: a deliberate 300 s GPS duty on a repeater was rewritten to 48 h
  on every boot (that migration now runs on legacy files only)
- one identity loader for all roles (IdentityFile); an unusable key
  file is always parked as .bad before regenerating
- server store no longer stamps repeater defaults on room server and
  observer; companion first-boot volume policy moved into the store
  (adoptVolume)
- ZephyrDataStore 1435 -> ~850 lines
2026-09-25 08:34:21 +02:00
liquidraver fd2cbe9d62 radio: extract CadController and NoiseFloorEstimator, one prefs source
- CadController (stats, window, re-anchor, visits, staircase, safety,
  starvation relax) and NoiseFloorEstimator split out of LoRaRadioBase
  behind a 4-call CadHw interface; Zephyr-free, host unit tests added
- prefs mandatory: setPrefs() before begin(), LoRaConfig fallbacks and the
  companion/observer placeholder prefs removed; LoRaConfig is the one
  defaults source (invalid-prefs fallback now uses the board TX default)
- TX-wait thread stack owned by the base; reconfigureWithParams removed
- driver extension headers on the public include path
  (zephyr/drivers/lora/*.h); patch 0003 include updated
- comment diet (image-identical); rationale moved to devdocs LLD 03
2026-09-23 14:33:29 +02:00
liquidraver a7d073900e core: restore upstream shape for the shared mesh core
- Mesh, Dispatcher, Packet, packet pool and the core headers rebuilt from
  Arduino MeshCore's text; ZephCore changes re-applied, each fenced
  `// ZEPHCORE:` (diff vs upstream: 4540 -> 1147 lines)
- upstream header layout; MainBoard gains handleCommand/loop and the other
  upstream members; RNG::nextInt back in Utils.cpp
- packet logging moved to the roles' log hooks (helpers/PacketLog.h)
- zero-hop direct ACKs deduplicated and length-checked as upstream
- RadioIncludes.h -> src/, LoRaConfig.h -> helpers/
- .editorconfig: shared files keep upstream formatting

Verified: 10 role builds, per-function disassembly review, bench DM/ACK
regression (T1000-E, Wio L1, XIAO S3 on 1.17.4) incl. via live repeater.
2026-09-23 13:39:48 +02:00
liquidraver bdf7348208 CAD offset safety net 2026-09-03 22:47:26 +02:00
liquidraver 7ae467305a transmit airtime fix 2026-09-03 19:02:51 +02:00
liquidraver 1633274e4f leds refactor/improvement 2026-09-03 14:34:12 +02:00
liquidraver ba33cebf6a cad improvements 2026-09-01 22:05:29 +02:00
liquidraver dc5b5c2594 radio driver fixes v1 2026-08-23 22:49:17 +02:00
liquidraver 46a6b34bdd switch defaults to sf7/cr5 2026-08-22 11:54:52 +02:00
liquidraver 9fc3ab7f7e PR70 fix 2026-08-20 21:13:15 +02:00
liquidraver 5c4ac21bd4 refactor patches and bump to 1.17.2 2026-08-20 17:50:48 +02:00
liquidraver ee90693c89 lr20xx: add freq-error summary log and get freqerr CLI 2026-08-12 15:12:43 +02:00
liquidraver a705d5b5ce refactor / unify probes 2026-07-29 12:30:47 +02:00
liquidraver fe6e585eb6 get rid of housekeeping tick and AGC reset 2026-07-28 14:12:40 +02:00
liquidraver 13b5e2fcf3 scrub APC and bump to 1.16.6 2026-07-20 09:55:32 +02:00
liquidraver 434a49375e try to improve APC 2026-07-17 08:35:08 +02:00
liquidraver 432336867b add cad.busycap knob for hilltop repeaters 2026-07-13 10:29:50 +02:00
liquidraver dc1239537e SmartCAD p1 2026-07-12 10:48:37 +02:00
liquidraver fc940d27ba sync with dev 2026-07-02 13:13:26 +02:00
liquidraver 2f86310500 port lora e5 mini 2026-06-21 20:38:57 +02:00
liquidraver 2ad185bab4 license "refactor" :) 2026-06-07 22:47:17 +02:00
liquidraver d37b401033 battery: centralized LiPo OCV curve + ADC multiplier corrections
Add a board-aware battery SOC system replacing the two independent
linear approximations that existed in the UI helpers.

New helpers/battery_curve.{h,c}: a 21-point (5% step) OCV lookup table
with integer linear interpolation. The default generic LiPo curve is a
weak symbol — any board can override it by dropping a battery_curve.c
into its board directory. CMakeLists.txt selects the board-specific file
when present, falling back to the generic.

Board.h gains getBattPercent() (default 0); ZephyrBoard implements it
via battery_curve_lookup().

Board-specific curves added for boards with measured cell data:
t1000_e, rak_wismesh_tag, thinknode_m6, sensecap_solar, wio_tracker_l1.

ADC multiplier corrections applied across all nRF52840 boards:
- Boards using a correctly-derived 3600×ratio formula get +0.5% to
  compensate for nRF SAADC gain error (7200→7236, 6300→6332, etc.)
- rak_wismesh_tag, rak3401_1watt, gat562_30s had multipliers copied
  from Arduino's 3.0V AREF formula; corrected to 3600×1.73×1.005=6259
- xiao_nrf52840 (10911) left unchanged — empirically calibrated value
  above the theoretical, assumed already correct for that hardware

get adc.multiplier now reports current mV reading and the board's
curve 100% target, making field calibration self-guiding.
2026-06-03 13:21:06 +02:00
liquidraver 7d7a64ff5a fix: airtime LDRO threshold must track driver (was BW-blind sf>=11)
getEstAirtimeFor() set LDRO from `sf >= 11`, correct only at BW125. Now
matches the driver's should_enable_ldro() (t_sym > 16.38 ms) so the
estimate's DE tracks hardware DE on every SF/BW. Also drop dead
calcRxDelay() + unused MAX_RX_DELAY_MILLIS.
2026-05-29 15:48:48 +02:00
liquidraver 94dcf61715 simplify app layer: dedup response/telemetry/JSON builders
- CompanionMesh: sendPacketSent() helper, collapse sendFloodScoped
  overloads, share self-telemetry LPP builder
- Mesh: shared computeAdaptive{Flood,Direct}Delay (was duplicated in
  Companion + Repeater)
- ObserverMesh/RepeaterMesh: shared helpers/MeshcoreJson.h builders;
  drop dead sign_input_len
2026-05-29 12:54:52 +02:00
liquidraver 799d694914 crypto: simplify entropy path after audit review
- Lift duplicated identity-gen block from main_companion.cpp +
  main_repeater.cpp into ZephyrRNG::generateFirstBootIdentity().
  Both mains shrink from ~40 lines to a 3-line helper call.
- Add LocalIdentity::fromSeed() so seed-derived keygen doesn't need
  a one-shot RNG wrapper; delete SeededRNG.
- Drop the per-byte ADC sampling loop: getBattMilliVolts() does an
  8-sample average + 10ms regulator settle internally, costing
  300-480ms of real wall-time and actively destroying the LSB jitter
  it was meant to harvest. Jitter mixer already dwarfs it.
- Centralize the printk + sys_reboot pattern as
  Utils::cryptoPanicReboot(); drop the 2000ms pre-reboot k_msleep
  (printk is synchronous, sleep just blocked the mesh thread on
  the ZephyrRNG::random() retry-failure path).
- Inline sample_cpu_jitter health check via online scalars instead
  of a 512-byte deltas[] array. Saves 1.5KB stack churn across boot
  and tracks every sample instead of only the first 128.
- extract_via_aes_ctr now uses Utils::sha256 instead of open-coding
  psa_hash_compute.
2026-05-29 07:58:54 +02:00
liquidraver b692ca72ed crypto: harden all crypto-sensitive memcmp + memset sites
Audit-driven sweep found additional compiler-optimization-sensitive
patterns beyond the login password compare just fixed:

P4.F3 (HIGH) — Utils::MACThenDecrypt verified packet MACs with
plain memcmp. Runs on EVERY encrypted-then-MAC'd packet in the
mesh; a timing oracle here lets attackers forge MACs byte-by-byte
across the whole mesh layer. Replaced with constantTimeEqual.

P4.F4 (MEDIUM) — Multiple memset(secret, 0, ...) calls on
stack-resident crypto buffers (Ed25519 seed, ADC noise pool, AES
key derived in extract_via_aes_ctr, HWINFO unique ID) were
subject to dead-store elimination under -Os. GCC/Clang routinely
elide these when the buffer is never read after; the wipe vanishes
and the secret persists on stack until next call overwrites.
Replaced with secureZeroize using volatile pointer writes.

P4.F5 (LOW) — Identity::validatePrivateKey boot self-test compared
shared secrets with plain memcmp. Boot-only, no attacker
observation channel, but hygiene matters and the fix is one line.
Also added secret-wipe for ss1/ss2 on all return paths.

Promoted the local ct_memeq() previously added to RepeaterMesh.cpp
into Utils::constantTimeEqual + Utils::secureZeroize (Utils.h/cpp)
so the login compare and MAC compare share the same audited helper.

Both helpers verified by Thumb-2 disassembly on rak3401_1watt:
- constantTimeEqual: loop branches on iterator, accumulator
  load-modify-stored to stack every iteration, final return uses
  CLZ+LSR (no conditional branch on result).
- secureZeroize: STRB.W to memory in a counted loop, not replaced
  with memset builtin and not eliminated.
2026-05-28 13:26:20 +02:00
liquidraver 6b624a69e5 sync with vnailla dev 2026-05-22 14:42:12 +02:00
liquidraver e778326ad0 joystick UI: handle SENT_HEARD/UNHEARD in buildChannelReplyPrefix
After Phase J, the joystick UI rewrites a sent channel message's
path_len from OUT_PATH_SENT (0xFE) to OUT_PATH_SENT_HEARD (0xFD) or
OUT_PATH_SENT_UNHEARD (0xFC) once the feedback window resolves.
buildChannelReplyPrefix only excluded OUT_PATH_SENT, so a reply to
one of the user's own messages (post-feedback) would treat it as
incoming and build a garbled "@[<random body>]" prefix.

Also cleans up an awkward `class ContentionTracker&` qualifier in
Mesh.h.
2026-05-21 22:31:51 +02:00
liquidraver 03fcc60fa9 joystick UI: channel-send heard-repeat feedback
After broadcasting a group message, wait 5s to see if any neighbor
repeated the flood and use the outcome to mark the on-device entry
and the BLE-app mirror.

  - ContentionTracker gets extractDupeCount(hash): finds the tracked
    entry, captures dupe_count, finalizes (folds into EMA, marks
    inactive), returns the count or -1.
  - BaseChatMesh::sendGroupMessage gains an optional out_hash param;
    when set, the FNV-1a packet hash is also pre-registered with the
    contention tracker so heard retransmits get counted (originated
    floods weren't tracked before, only relays).
  - Mesh::getContentionTracker() promoted to public so the UI can
    query after the feedback window.

JoystickUITask grows a 4-slot pending-channel table with per-slot
k_timer (5s one-shot). startPendingChannel() broadcasts, adds the
local _ch_previews entry with path_len = OUT_PATH_SENT, and starts
the feedback timer. The timer ISR sets a feedback_due flag; the
loop's processPendingChannelFeedback() picks it up, calls
extractDupeCount(), and rewrites the preview's path_len to
OUT_PATH_SENT_HEARD (0xFD) or OUT_PATH_SENT_UNHEARD (0xFC) — which
formatHopCount renders as "sent+" / "sent?".

The deferred BLE-app mirror queues only on outcome with body prefix
"(>>✓) " (heard) or "(>>✗) " (not heard). queueLocalSentChannelMessage
gains a heard_repeat parameter for the selection.

Both channel send entry points (sendComposedMessage's channel branch
and sendChannelMessage) now route through startPendingChannel().
2026-05-21 22:24:26 +02:00
liquidraver bd1e022e88 fix(security): close OOB read in path-decoding callers (BLE + LoRa-anon)
Both mesh::Packet::writePath and ::copyPath did a raw memcpy of the
decoded hash_count*hash_size bytes from src to dest with no bound on
src. Two call sites used phone-supplied or LoRa-anon-supplied buffers
where the path_len byte was attacker-controlled:

  - CompanionMesh CMD_SEND_CHANNEL_DATA accepted len>=4 and called
    writePath with no src bound; a paired phone could leak up to ~65
    bytes of syswq stack into the outgoing LoRa channel-data frame.

  - RepeaterMesh handleAnonRegionsReq / handleAnonOwnerReq /
    handleAnonClockReq read reply_path_len from an unauthenticated
    LoRa anon-request payload and called copyPath without any src
    bound. Any LoRa neighbor could leak repeater stack into the
    reply path.

Hardened the API: both functions now require an explicit src_len
and reject (return 0) when the decoded byte count exceeds it.
Updated all 14 call sites across Packet/Mesh/Dispatcher/BaseChatMesh/
CompanionMesh/RepeaterMesh. Trusted callers (internal MAX_PATH_SIZE
buffers) pass MAX_PATH_SIZE; untrusted callers pass real remaining
length. Added len-5 plumbing through the anon-handler signatures.

CMD_SEND_CHANNEL_DATA also gained a local len>=5 + path_bytes
sanity check for early rejection.
2026-05-20 11:52:39 +02:00
liquidraver 3441caf8b0 new rx busy latch 2026-05-14 22:24:48 +02:00
liquidraver 6919c3511c rx_boost state is undefined at boot (minor fix)
every LBT-retried flood packet loses its priority (fixed)
witching between LBT and non-LBT mode (or any cad.mode change) could silently skip full reconfiguration and leave the radio in the wrong mode (fixed)
2026-05-08 09:50:52 +02:00
liquidraverandClaude Opus 4.7 5e7adfb130 normalize source-file line endings to LF
Add .gitattributes rules so .c/.h/.cpp/.hpp are always stored as LF
(prevents EOL drift from editors with autocrlf-true defaults), and
renormalize the 30 source files that had drifted to CRLF in the index.

Pure mechanical change — `git diff --ignore-cr-at-eol` is empty.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-05 14:56:44 +02:00
liquidraver a81f27aea4 implement "isradioready" for early returns in rx duty cycling 2026-04-30 21:54:59 +02:00
liquidraver 1092c49a7d port vanilla duty cycling logic 2026-04-28 14:43:12 +02:00
liquidraver b57df41753 micro-tweak: skip APC math when APC is off 2026-04-28 14:18:10 +02:00
liquidraver bf9ad0ef40 tune delay knobs 2026-04-28 13:49:08 +02:00
liquidraver ba4b86752d acw: airtime-scale jitter caps, companion surroundings awareness
- flood retransmit jitter now capped at min(2000ms, 6·airtime) instead of
  fixed 2000ms — spreads tighter at SF7, unchanged at SF8
- reactive per-dupe backoff cap now min(2000ms, 12·airtime), keeps
  semantic of "push past ~12 relay slots"
- contention ring 16 → 24 for 50-neighbor hilltops
- companions passively track heard floods (warms EMA without forwarding)
  and spread their own TX by up to min(1000ms, 3·airtime), hopefully
  fixing repeaters missing companion's first transmission

config cleanup:
- move BLE TX buffer bumps (ACL_TX=12 etc.) from zephcore_common.conf to
  esp32_common.conf — the Espressif blob needs them, nRF doesn't, and
  the bumps were overflowing nRF52840 RAM
- remove CONFIG_ZEPHCORE_MAX_CONTACTS=510 overrides from 5 nRF52840
  companion boards; Kconfig default of 350 fits with comfortable margin
  (wio prod: 91% → 79% RAM)
2026-04-17 10:24:12 +02:00
Rastislav Vysoky da22b127c3 sx1276 2026-04-07 19:05:32 +02:00
liquidraver 33fa19a7f5 comment overhaul 2026-03-28 20:53:59 +01:00
liquidraver 8dd6f149f8 sync with arduino/dev 2026-03-24 20:36:36 +01:00
liquidraver ccaba52f3c tune contentiontracker 2026-03-20 22:12:15 +01:00
liquidraver 0bf8bd72a3 promicro LR2021 build fix 2026-03-16 19:49:53 +01:00
liquidraver 4ad8b13756 reactive backoff tuning 2026-03-15 21:14:21 +01:00
liquidraver d794b57e31 APC second test
This reverts commit 4bd84ddf7e.
2026-03-14 21:15:57 +01:00
liquidraver 4bd84ddf7e APC first test 2026-03-14 14:01:10 +01:00
liquidraver d45fbf7027 reactive collision avoidance 2026-03-11 12:08:48 +01:00