Commit Graph

92 Commits

Author SHA1 Message Date
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
DeFiDude
00d04284c1 v1.6.3: Fix LXMF wire format, add link-based delivery
Some checks failed
PlatformIO Build / build (push) Failing after 12m51s
PlatformIO Build / release (push) Has been skipped
Fix opportunistic LXMF wire format to match Python reference
(strip dest_hash from payload, carried by RNS packet header).
Compute messageId in packFull() matching Python LXMessage.pack().
Prepend dest_hash in onPacketReceived() for correct unpack.
Add opportunistic-first delivery with background link establishment.
Fix boot crash from RNS::Link default constructor in global scope.
v1.6.3
2026-03-19 14:37:09 -06:00
DeFiDude
8b8a9b572f Add link-based LXMF delivery, fix display SPI contention
Display: switch pushPixelsDMA to blocking pushPixels to prevent SPI bus
contention between the display and SX1262 radio on the shared FSPI bus.

LXMF: add opportunistic-first delivery with background link upgrade.
First message to a peer sends immediately via opportunistic packet. A
link is established in the background; subsequent messages use the link
when active (prepending dest_hash for Python DIRECT format), falling
back to opportunistic otherwise. No user-facing delay.
2026-03-19 13:07:19 -06:00
DeFiDude
71849cbb62 Fix LXMF wire format for Python interoperability
Opportunistic (non-link) delivery must strip dest_hash from the LXMF
payload — it's carried by the RNS packet header. Python prepends it
back on receive; we now do the same. Previously ratdeck always included
dest_hash when sending and never prepended it when receiving, breaking
interop in both directions.

- packFull: return [src:16][sig:64][msgpack] instead of [dest:16][src:16][sig:64][msgpack]
- onPacketReceived: prepend dest_hash from packet header before unpacking
- sendDirect: use messageId computed by packFull instead of re-hashing wire payload
- Add docs/WIRE-FORMAT.md documenting the exact format for all delivery methods
2026-03-19 12:37:09 -06:00
DeFiDude
2c161238c7 Fix messageId hash to exclude signature, matching Python/Rust
Some checks failed
PlatformIO Build / build (push) Failing after 7m56s
PlatformIO Build / release (push) Has been skipped
messageId was computed as SHA256(dest+src+sig+payload) but Python/Rust
compute SHA256(dest+src+payload) — skipping the 64-byte signature.
This caused message ID mismatches across implementations, breaking
deduplication and propagation node lookups.
2026-03-17 18:11:35 -06:00
DeFiDude
d89b6699ab v1.6.2: Fix announce bin8 encoding in Settings, deduplicate encodeAnnounceName
Some checks failed
PlatformIO Build / build (push) Failing after 30s
PlatformIO Build / release (push) Has been skipped
Apply bin8 fix to the duplicate announce encoding in LvSettingsScreen
(Send Announce action). Replace inline copy with shared function from
main.cpp. Follows up on PR #5.
v1.6.2
2026-03-15 12:32:54 -06:00
dude.eth
e3dffe6df2 Merge pull request #5 from scotty007/fix/announce-format
Fix msgpack format of announce app data
2026-03-15 12:27:22 -06:00
DeFiDude
fc91f8214e TCP scaling, GUI pooling, dev mode, protocol improvements
- TCP: wider drain budgets, TCP_NODELAY, no flush, PSRAM buffers, queue announces until hub ID
- GUI: object pool Messages/Contacts screens, partial MessageView status, targeted tab refresh
- LVGL throttled to 5fps when dimmed, non-blocking RSSI monitor, bounded I2S writes
- LXMF batch drain, BLE frame mutex, LoRa interrupt-driven RX, name cache cap 300
- Developer mode in settings: custom radio params (freq/txp/SF/BW/CR/preamble) behind warning
2026-03-15 12:25:29 -06:00
Scotty
d9097c0289 Fix msgpack format of announce app data 2026-03-15 13:26:09 +01:00
DeFiDude
02d7dedcce v1.6.1: Fix TCP port input, flash status, PSRAM audio optimization
- Fix TCP port input: allow direct digit entry instead of scroll-only
- Fix flash status always showing "Error" (was checking SD path on flash)
- Flash now shows used/total KB instead of just Mounted/Error
- Audio buffers use PSRAM (ps_malloc) with internal heap fallback
- Bump version to 1.6.1
v1.6.1
2026-03-13 13:42:17 -06:00
DeFiDude
813a14641f v1.6.0: Update microReticulum ref, LXMF fixes, bump version v1.6.0 2026-03-13 04:24:29 -06:00
dude.eth
c4669a2fcc Update README.md 2026-03-12 15:50:05 -06:00
dude.eth
ec66d24aa3 Update README.md 2026-03-12 15:42:22 -06:00