104 Commits

Author SHA1 Message Date
DeFiDude
6836b6967a Fix bidirectional comms regression: remove unsafe core 0 persist task, restore better-path announce bypass
Increase TCP drain budget (5→10 frames), raise RNS-overload skip threshold (200→500ms)
2026-03-30 02:15:22 -06:00
DeFiDude
0d2a75a71c Remove the pesky 0.1% Python 2026-03-30 01:32:44 -06:00
DeFiDude
33ce7eab56 Shorten LoRa preset labels, default to Long Fast 2026-03-30 01:21:33 -06:00
Belousov Oleg
4b35318121 Fix: custom label in Lora presets 2026-03-29 13:25:56 +03:00
Belousov Oleg
8ea5993e8d The list of Lora presets has been expanded 2026-03-29 13:18:11 +03:00
DeFiDude
16412067e0 v1.7.3: performance, Cyrillic fonts, scroll/UI fixes v1.7.3 2026-03-28 22:40:42 -06:00
DeFiDude
15e0e67610 Set microReticulum log level to WARNING, document verbose logging for debugging 2026-03-28 22:21:05 -06:00
DeFiDude
bcba228635 Move flash persistence to core 0 background task, eliminate 4s main loop freeze 2026-03-28 22:07:43 -06:00
DeFiDude
2c73a10c80 Hide unknown hop count, remove hops_to and toHex from transport filter hot path 2026-03-28 21:18:08 -06:00
DeFiDude
9e4217085a Reduce device freeze on large TCP hubs, reduce announce processing overhead 2026-03-28 21:11:31 -06:00
DeFiDude
59200d6aea Cyrillic and Latin Extended font support (fixes #14)
Regenerated Montserrat 10/12/14 with Cyrillic and Latin Extended
Unicode ranges so messages in Russian, Ukrainian, Bulgarian, and
accented European languages render properly instead of rectangles.
2026-03-28 20:58:01 -06:00
DeFiDude
4958ed9289 Fix nodes list scroll truncation, center action modal, trackball parity
Scroll: scrollToSelected() was defined but never called — LVGL didn't
know which pool row to show after viewport updates. Nodes at the
bottom of long lists were invisible. Now called after every sync.

Modal: Replace lv_obj_center() with explicit pixel positioning so
the action modal renders centered regardless of list scroll state.

Trackball: Click now sets character='\n' matching keyboard Enter for
complete event parity.
2026-03-28 20:37:48 -06:00
DeFiDude
a32c6d9a42 Prevent selecting Custom preset, detect custom frequency in preset v1.7.2 2026-03-28 19:47:27 -06:00
DeFiDude
e92a013caf v1.7.2: idle optimization, regional presets, RSSI, UX improvements 2026-03-28 19:43:14 -06:00
DeFiDude
d81921357b Stamp incoming messages with receiver time, radio-style freq editor
Timestamps: Incoming messages with invalid sender timestamps
(< Nov 2023 epoch) are now stamped with the receiver's local time
if available. Previously, messages from devices without NTP/GPS
showed no timestamp at all.

Frequency editor: Replace raw 9-digit Hz accumulator with a
radio-style digit cursor. Display shows NNN.NNN.NNN format with
bracket cursor on active digit (e.g., "920.[6]50.500"). Trackball
left/right moves cursor, digit keys replace at cursor and advance.
Esc restores original value. Matches amateur radio transceiver UX.
2026-03-28 16:25:50 -06:00
DeFiDude
f41e4c0363 Tune RNS tables, cache status bar time, add BLE idle timeout
Status bar: Cache last displayed hour/minute, skip LVGL label
update when minute hasn't changed (eliminates 59/60 redundant
invalidations per minute).

RNS tables: Increase ANNOUNCE_TABLE_MAX 32→48 (prevents premature
eviction on networks >32 nodes). Increase RATE_TIMESTAMPS_MAX
16→32 (prevents false rate-limit rejects on busy networks).

BLE: Add 5-minute idle timeout. Stale connections now get
disconnected to free the single NimBLE connection slot for new
devices. Activity tracked on connect, RX, and TX events.
2026-03-28 15:51:43 -06:00
DeFiDude
d3ed421038 Optimize message view rendering, WiFi TX buffering, remove unused font
Message view: Extract appendMessage() from rebuildMessages(). New
messages are now incrementally appended (O(delta) widget ops) instead
of destroying and recreating all bubbles (O(N)). Full rebuild only
on initial load or message count decrease.

WiFi TX: Buffer HDLC frame in PSRAM then send with single write()
call. Previously sent per-byte (200+ syscalls per packet), now 1
syscall. Reduces CPU overhead and TCP fragmentation.

Font: Disable unused LV_FONT_UNSCII_8 (compiled but never referenced).
2026-03-28 15:48:40 -06:00
DeFiDude
c3025eb98e Fix TCP stack overflow risk and cap WiFi AP client connections
TCP: Move 2KB stack-allocated packet rewrite buffers in
send_outgoing() to a PSRAM-allocated member (_wrapBuffer).
The ESP32-S3 loop task has 8KB stack — a single 2KB VLA used
25%, risking overflow under deep call chains during TCP load.

WiFi AP: Cap concurrent client connections at 4. Previously
unbounded — any number of clients could connect and exhaust
memory. New clients beyond the limit get a clean TCP RST.
2026-03-28 15:43:49 -06:00
DeFiDude
16f1bb516c Show WiFi reboot toast only once, not on every setting change
Previously, "Reboot Required!" fired on every applyAndSave() once
any WiFi setting changed — showing 3 times during a single STA
setup (mode + SSID + password). Now the toast only shows on first
detection with a gentler message: "WiFi changes apply on reboot".
Subsequent saves show "Saved" normally.
2026-03-28 15:26:24 -06:00
DeFiDude
7bf1be2724 Fix GPS time not showing without satellite lock (LoRa-only boot)
Two-layer fix:
- NMEAParser: parse time fields from RMC sentences even when status
  is void ('V'). The MIA-M10Q's battery-backed RTC provides time in
  every sentence — we were discarding it along with the void location.
- GPSManager: allow first time sync without satellite lock. Subsequent
  syncs still require sats>0 for accuracy. Year/epoch validation still
  guards against garbage data from uninitialized modules.

Previously, time only appeared after WiFi connection (NTP via
configTzTime). Now the clock shows within seconds of boot using the
GPS module's RTC, then corrects when satellites lock.
2026-03-28 15:16:57 -06:00
DeFiDude
4086609054 Fix stale unread badge when message arrives during active conversation
refreshUI() detected and displayed new messages but never called
markRead() or updated the tab badge. Now marks conversation as read
and refreshes the badge whenever new messages are loaded while the
user is actively viewing the conversation.
2026-03-28 14:51:26 -06:00
DeFiDude
31ce457192 Add action modal for node selection (Add Contact / Message / Back)
Replace direct-message-on-Enter with a 3-option modal overlay:
- "Add Contact" prompts for a nickname (pre-filled with announce
  name, falls back to hex hash if left empty), then saves contact
- "Message" opens conversation (previous Enter behavior)
- "Back" closes modal (also Esc at any point)

Long press on unsaved nodes now also shows the modal instead of
silently adding. Long press on saved contacts keeps the existing
delete confirmation flow.
2026-03-28 14:38:59 -06:00
DeFiDude
6cd4197503 Add per-node RSSI/SNR display on Nodes screen (developer mode)
Backend:
- LoRaInterface captures packet RSSI/SNR immediately after every RX,
  removing redundant SPI re-reads from log statements
- AnnounceManager populates DiscoveredNode.rssi/snr from LoRaInterface
  on every announce (fields existed but were never wired up)

Frontend:
- Nodes screen shows RSSI appended to hops/age when dev mode is on
- Node name label uses smaller font (montserrat_12) to reduce truncation
- Normal users see no change
2026-03-28 14:27:07 -06:00
DeFiDude
a77fb594a2 Fix screen wake on idle, add regional frequency presets and Hz input
Screen idle:
- Remove powerMgr.activity() from radio yield callback — screen no
  longer wakes on LoRa RX, auto-announce, or RSSI polls
- Add [POWER] state transition logging for on-device diagnostics

Radio regions:
- Add 4-region system: Americas (915), Europe (868), Australia (915),
  Asia (923) with timezone-to-region mapping
- Region picker in Radio settings (always visible)
- Presets now apply region-appropriate frequency + modulation params
- Timezone change warns if it suggests a different radio region

Frequency input (developer mode):
- Hz-precision input (9 digits) displayed as MHz with trimmed decimals
- Left/right arrows step by 125 kHz, digit keys for direct entry
- Inspired by @strijar in https://github.com/ratspeak/ratdeck/pull/12
2026-03-28 14:06:31 -06:00
DeFiDude
b2fcfe526e v1.7.1: GPS time sync, timezone picker, status bar clock
- GPS time sync via UBlox MIA-M10Q (38400 baud auto-detect)
- Custom zero-dependency NMEA parser with XOR checksum validation
- Only trust GPS time when satellites > 0 (no stale RTC cache)
- DST-aware timezone picker at first boot (21 cities, POSIX TZ strings)
- Timezone also configurable in Settings > GPS/Time
- GPS Time on by default, GPS Location off by default (opt-in)
- Status bar: clock (top-left), Ratspeak.org (center), battery (right)
- 12h time default (no AM/PM), configurable 24h in settings
- NVS persistence of GPS time for approximate timestamps across reboots
- Fix factory reset Enter key bleed-through (600ms input guard)
- Fix hardcoded UTC-5 NTP timezone (now uses DST-aware POSIX TZ)
v1.7.1
2026-03-25 02:42:18 -06:00
DeFiDude
311c5ad3df GPS time sync, status bar clock, configurable UTC offset
- Enable UBlox MIA-M10Q GPS on T-Deck Plus (HAS_GPS true)
- Custom zero-dependency NMEA parser (NMEAParser.h) with XOR checksum
- GPSManager: baud auto-detect (115200/38400/9600, 10s timeout),
  settimeofday() sync every 60s, NVS time/position persistence
- GPS Time enabled by default, GPS Location disabled by default
  (user must explicitly opt in via Settings)
- Replace status bar connectivity bars with clock display (top-left)
- Default 12h format without AM/PM, configurable 24h in Settings
- Add GPS/Time settings category: GPS Time, GPS Location,
  UTC Offset (-12 to +14), 24h Time toggle
- Fix hardcoded UTC-5 NTP timezone to use configurable utcOffset
- Change status bar brand text to "Ratspeak.org"
2026-03-25 01:36:56 -06:00
DeFiDude
31cbab7fc2 Remove merged bin from firmware zip (already a separate release asset) 2026-03-24 23:31:50 -06:00
DeFiDude
fad3de7057 v1.7.0: LoRa split-packet framing, hub performance, silent auto-announce v1.7.0 2026-03-24 23:12:11 -06:00
DeFiDude
6df6017ab4 Suppress UI notifications for auto-announce when screen is off 2026-03-24 22:29:26 -06:00
DeFiDude
949e508f80 Reduce table caps for client device performance
Lower known_destinations from 512→128, announce_table from 128→32,
path_table from 256→64. Ratdeck is a client, not a transport node —
smaller tables reduce cull overhead and memory pressure on busy hubs.
2026-03-24 22:23:15 -06:00
DeFiDude
851da63220 LoRa split-packet framing, TX queue, and LXMF delivery fixes
LoRaInterface: Implement RNode-compatible split-packet framing so the
full Reticulum MTU (500 bytes) works over LoRa. Packets >254 bytes are
transparently split into two LoRa frames with matching sequence numbers
and reassembled on the receiver. Also adds a 4-deep TX queue instead of
dropping packets when the radio is busy — critical for link handshakes.

LXMFManager: Large messages (>MDU) now queue pending link establishment
and retry via resource transfer instead of failing immediately. Stale
link-pending state is detected and reset. Speculative background link
establishment removed to avoid LoRa collisions.

AnnounceManager: Add app_data hex diagnostics on announce RX for
debugging name extraction issues.

main.cpp: Centralize all announce paths through announceWithName() so
display name and app_data are always logged.
2026-03-24 20:55:07 -06:00
DeFiDude
2221eb832f Route large LXMF messages through Resource transfer over link
When link payload exceeds MDU (263 bytes), use Link::start_resource_transfer()
instead of failing. This enables sending files, images, and long messages
(>295 bytes content) via the microReticulum Resource protocol.

Delivery path selection:
1. Link active + payload ≤ MDU → single link packet (existing)
2. Link active + payload > MDU → Resource transfer (NEW)
3. No link → opportunistic (existing, fails for >MDU)
2026-03-24 17:06:43 -06:00
DeFiDude
cc8701436e Remove local LXMFMessage — now provided by microReticulum library
LXMFMessage.h/cpp is now part of the microReticulum library (commit 6f3c08d).
This eliminates the duplicate LXMF codec and ensures all platforms (Ratdeck,
Ratcom, native tests) use the same shared implementation.

The local header is replaced with a forward to <LXMFMessage.h> so existing
#include "LXMFMessage.h" references still resolve.

microReticulum library includes 32 tests validating the LXMF codec:
- 10 pack/unpack/sign tests (test_lxmf_codec)
- 10 cross-platform fixture tests (test_lxmf_interop)
- 6 announce interop tests (test_announce_interop)
- 6 protocol edge case tests (test_protocol_edge_cases)
2026-03-24 16:22:47 -06:00
DeFiDude
5fd01251dd v1.6.6: LoRa stability, announce interval config, touch input fix v1.6.6 2026-03-23 18:09:09 -06:00
DeFiDude
8c0b0853e4 Fix GT911 touch coordinate axes for T-Deck Plus display orientation
Swap X/Y axes and invert Y so (0, 0) maps to the top-left corner,
matching the physical display orientation on the T-Deck Plus.
Patch suggested by scotty007 in PR #10.
2026-03-23 17:57:34 -06:00
dude.eth
f060b892b9 Merge pull request #10 from scotty007/fix/read-touch-input
Fix touch input reading
2026-03-23 17:56:30 -06:00
Scotty
3b1772147b Fix register address and size of GT911 point data 2026-03-22 09:20:43 +01:00
Scotty
67a682080d Store and use I2C address at which GT911 was found 2026-03-22 09:05:41 +01:00
DeFiDude
f1cf2e654c Fix ISR deadlock crash: remove SPI call from DIO1 interrupt handler 2026-03-21 14:48:39 -06:00
dude.eth
92e02f5442 Merge pull request #9 from scotty007/feature/config-announce-interval
Add user config setting for auto-announce interval
2026-03-21 14:35:51 -06:00
DeFiDude
0c4fbb5cd5 Drop oversized LoRa packets instead of silently truncating
The previous LORA_SAFE_LINK_PAYLOAD check only guarded link delivery,
but opportunistic delivery also exceeds the 255-byte LoRa MTU for longer
messages. Truncated packets corrupt the HMAC/ciphertext, wasting airtime
and confusing receivers.

Fix: LoRaInterface::send_outgoing() now rejects packets exceeding
MAX_PACKET_SIZE before they reach the radio. This is a hard limit —
messages too large for a single LoRa packet will not be sent until
Resource-based multi-packet transfer is implemented.
2026-03-21 14:14:34 -06:00
DeFiDude
4a7b1935d5 Workaround LoRa link delivery truncation for large LXMF messages
Link delivery adds ~64 bytes of overhead (dest_hash + Token IV/HMAC/padding)
which can push encrypted payloads past the 255-byte LoRa MTU. SX1262::write()
silently truncates, corrupting the HMAC and failing decryption on the receiver.

Band-aid: cap link delivery plaintext at 180 bytes, falling back to
opportunistic delivery for larger messages. Long-term fix needed: negotiate
link MTU based on interface HW_MTU, or implement Resource-based multi-packet
transfer for oversized payloads.
2026-03-21 14:00:12 -06:00
Scotty
42c5a8b1a5 Add user config setting for auto-announce interval 2026-03-21 11:35:10 +01:00
DeFiDude
6f8e53c060 Fix LoRa TX killed by receive() after handle_incoming (untested)
Some checks failed
PlatformIO Build / build (push) Failing after 13m14s
PlatformIO Build / release (push) Has been skipped
2026-03-21 02:19:07 -06:00
DeFiDude
87723e891a v1.6.5: Disable BLE by default, remove DataCleanScreen prompt v1.6.5 2026-03-20 20:42:37 -06:00
DeFiDude
b70342a2f5 Fix wrong-recipient message delivery via stale outbound link
When switching between peers, sendDirect() updated _outLinkDestHash to the
new destination before the new link was established, while _outLink still
held the old peer's active link. On the next retry, the hash check passed
(both matched the new peer) but the link object was still connected to the
old peer — delivering the message to the wrong recipient.

Fix: only update _outLinkDestHash in onOutLinkEstablished() when the new
link is actually ready. Use _outLinkPendingHash to track what's being
connected to.
2026-03-20 20:25:47 -06:00
DeFiDude
e250ea1ad0 Switch microReticulum dependency to fork master branch
Some checks failed
PlatformIO Build / build (push) Failing after 7m17s
PlatformIO Build / release (push) Has been skipped
All fixes from fix/tcp-transport-and-identity-persistence have been
merged into master on ratspeak/microReticulum. No need for the branch
reference anymore.
2026-03-20 19:47:47 -06:00
DeFiDude
ca9c736a2a v1.6.4: Bump version for LXMF bidirectional messaging fix 2026-03-20 19:43:09 -06:00
DeFiDude
43e5420416 Fix LXMF bidirectional messaging, increase known_destinations cap
Outbound (Ratdeck→Python) was broken because Identity::recall() could
never find the recipient. Root cause: OS::time() returns seconds since
boot on ESP32, but persisted known_destinations entries carried timestamps
from the previous session. New announces got timestamp ~31s while persisted
entries had ~5000s, so the LRU cull immediately removed the new entry.

The microReticulum Identity.cpp fix (timestamp normalization on load) is
in .pio/libdeps and must be upstreamed to ratspeak/microReticulum separately.

Changes:
- known_destinations cap 256→512 (PSRAM pool was 1% used, plenty of room)
- Fix link delivery destHash: onLinkEstablished callback was passing link_id
  instead of LXMF destination hash, corrupting conversation routing
- Add diagnostic logging: [LXMF-DIAG], [TCP-DIAG], [HEART-DIAG], [DIAG-PROOF]
  for tracing link establishment, proof routing, and interface status
2026-03-20 19:24:28 -06:00
DeFiDude
45df807424 Fix TCP announce flood: adaptive filter, TCP backpressure, aligned table caps
- Enhanced announce filter: adaptive rate (3/sec boot, 5/sec normal),
  skip re-validation of known paths unless hop count improved or 5min
  revalidation window expired
- Skip TCP reads when RNS loop exceeds 200ms to prevent UI starvation
- Lower MAX_ANNOUNCES_PER_SEC from 8 to 5
- Align build flag table caps (256/128) with runtime values
2026-03-19 15:24:31 -06:00