Commit Graph
100 Commits
Author SHA1 Message Date
sjgandClaude Sonnet 4.6 8cb6292c1d [fix](trx-client): reduce events source latency to <1 s
Three causes of >30 s SSE stalls:

1. SPECTRUM_IO_TIMEOUT was 300 ms — transient server jitter triggered
   false-positive spectrum failures and immediate TCP disconnects.
   Raised to 1 s to tolerate brief load spikes.

2. reconnect_delay was never reset after a successful TCP connect, so
   after a few spectrum-induced disconnects the backoff reached 10 s.
   Each new disconnect then cost 10 s of stale SSE state, and several
   cycles accumulated to >30 s.  Reset to 1 s on every successful
   TCP connect so recovery stays fast.

3. SSE pings were emitted as comments (": ping"), which EventSource
   never exposes to onmessage.  lastEventAt was therefore never updated
   by pings, causing the JS heartbeat to force-reconnect every ~20 s
   even on healthy, stable connections.  Changed to a named "ping"
   event and added es.addEventListener("ping", …) to update lastEventAt.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-09 22:13:53 +01:00
sjgandClaude Sonnet 4.6 824434e27e [fix](trx-frontend-http): avoid double JSON parse/serialize in /events
inject_frontend_meta was calling serde_json::from_str + to_string on
every state update, adding two full JSON round-trips per SSE event.
Replace with string-level injection: strip the closing }, serialize only
the extra meta fields once, and re-close the object. The state JSON is
now serialized exactly once per update.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-09 21:46:37 +01:00
sjgandClaude Sonnet 4.6 75355c75a5 [feat](trx-frontend-http): encode spectrum bins as compact i8/base64 SSE
Replace the JSON f32 array (~7.5 KB/frame) with a named SSE event "b"
carrying base64-encoded i8 bins (~1.4 KB/frame, ~5x reduction):

  event: b
  data: {center_hz},{sample_rate},{base64_i8_bins}

1 dB per step covers the -128…+127 dBFS display range, sufficient for
visualization. RDS is stripped from the spectrum frame and emitted as a
separate named "event: rds" only when the payload changes. The JS
decoder uses atob() + sign-extension to reconstruct the float bin array.
A minimal inline base64 encoder is added server-side (no new crate).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-09 21:34:11 +01:00
sjgandClaude Sonnet 4.6 1d8b77ae44 [fix](trx-server): remove unused AsyncWriteExt import
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-09 21:24:25 +01:00
sjgandClaude Sonnet 4.6 409b173f62 [feat](trx-server): gzip-compress history replay blob
Add flate2 dependency and a new AUDIO_MSG_HISTORY_COMPRESSED (0x0a)
wire type. The server gzip-compresses the full history blob before
sending; JSON history compresses ~10-20x so both transfer size and
client wait time drop significantly. The client decompresses and
dispatches sub-messages from the embedded framed stream. MAX_PAYLOAD_SIZE
is kept at 1 MB for normal messages; a separate 16 MB limit is applied
only to the compressed history type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-09 21:17:49 +01:00
sjgandClaude Sonnet 4.6 26fbd37b6d [feat](trx-frontend-http): wire HF APRS toggle button and bookmark decoder
- Add "Enable HF APRS" toggle button to the HF APRS tab (same style as
  FT8/WSPR); button is disabled during TX like other decoder toggles
- app.js: sync button text/colour from SSE state updates
- hf-aprs.js: connect button click to /toggle_hf_aprs_decode
- bookmarks.js: add "HF APRS" checkbox to Add/Edit Bookmark decoder
  section; bmReadDecoders/bmWriteDecoders handle "hf-aprs" key; bmApply
  toggles the decoder to match bookmark preference on recall

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-08 20:43:55 +01:00
sjgandClaude Sonnet 4.6 ac586418fc [fix](trx-rs): add AUDIO_MSG_HF_APRS_DECODE wire type for HF APRS
Assigns message type 0x09 to HF APRS decoded frames on the binary
audio TCP channel and wires it up in all three layers:
- trx-core: AUDIO_MSG_HF_APRS_DECODE = 0x09
- trx-server: emit 0x09 in the live dispatch match and include
  hf_aprs history in the connection-open replay blob
- trx-client: recognise 0x09 and forward to the decode broadcast

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-08 20:26:23 +01:00
sjgandClaude Sonnet 4.6 19d6d2e50b [feat](trx-rs): add HF APRS decoder (300 baud, 1600/1800 Hz AFSK)
Adds a second APRS demodulator path tuned for the HF APRS standard
(300 baud Bell 103-style AFSK, mark=1600 Hz / space=1800 Hz), active
on RigMode::DIG.  Shares AX.25 framing, APRS parsing, APRS-IS uplink,
and frontend display with the existing VHF stack.

- trx-aprs: parameterise Demodulator::new(); add AprsDecoder::new_hf()
- trx-core: HfAprs variant in DecodedMessage; hf_aprs_decode_enabled /
  hf_aprs_decode_reset_seq in RigState/RigSnapshot; SetHfAprsDecodeEnabled
  and ResetHfAprsDecoder commands; handlers.rs fallback arm updated
- trx-protocol: client command variants + bidirectional mapping; test
  fixture updated
- trx-server: run_hf_aprs_decoder() task (activates on DIG mode);
  hf_aprs history in DecoderHistories; rig_task command dispatch;
  aprsfi uplink forwards HfAprs via OR-pattern
- trx-frontend: hf_aprs_history in FrontendRuntimeContext
- trx-frontend-http: prune/record/snapshot/clear helpers; SSE history
  replay; toggle_hf_aprs_decode + clear_hf_aprs_decode endpoints;
  /hf-aprs.js endpoint; HF APRS tab in web UI

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-08 20:17:37 +01:00
sjgandClaude Sonnet 4.6 ee821a71b1 [fix](trx-frontend-http): avoid per-draw GPU realloc in WebGL renderer
Safari stalls noticeably on gl.bufferData (which reallocates the GPU
buffer) when called multiple times per frame. Replace with a pre-
allocated scratch Float32Array and gl.bufferSubData, which only uploads
new data without reallocating. The GPU buffer is grown with bufferData
only when the scratch outgrows it (amortised doubling). Also eliminate
the per-draw-call `new Float32Array(vertices)` allocation in favour of
scratch.set() + subarray(), removing per-frame GC pressure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-08 18:51:34 +01:00
sjgandClaude Sonnet 4.6 250300395f [fix](trx-server): batch history replay into single TCP write
Replace per-message write + flush-every-64 with a single in-memory blob
that is sent via one write_all + one flush. Add estimated_total_count()
to DecoderHistories for pre-allocation. Eliminates N/64 partial flushes
and repeated small writes that dominated replay latency for large APRS
histories.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-08 18:39:50 +01:00
sjgandClaude Sonnet 4.6 6c4853c88c [fix](trx-frontend-http): remove per-packet console.log from APRS handler
During history restore with thousands of APRS packets, the console.log
in addAprsPacket was called for every entry, slowing the replay down
significantly. Remove it entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-08 18:37:55 +01:00
sjg f8d7472510 [fix](trx-vdes): fix VDES warm-up period
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-08 08:44:41 +01:00
sjgandClaude Sonnet 4.6 b4fb42dba4 [fix](trx-server): clear CW history on ResetCwDecoder
ResetCwDecoder already bumped cw_decode_reset_seq but omitted the
history flush that APRS, FT8, and WSPR all perform.  Wire
clear_cw_history() into the handler to match the pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 10:17:39 +01:00
sjgandClaude Sonnet 4.6 cbf3301664 [fix](trx-server): remove unused clear_cw_history method
No reset event for CW is wired in rig_task.rs, so the method was
dead code and triggered a compiler warning.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 10:16:36 +01:00
sjgandClaude Sonnet 4.6 53199642ea [fix](trx-server): fix VDES channel routing and IQ sample rate
Subscribe to the first sdr.channels[] entry configured as VDES or
MARINE instead of always using channel 0.  The ChannelDsp IQ tap only
emits samples when its own mode is VDES/MARINE, so the two must agree.

Fix vdes_sr to mirror channel.rs pipeline_rates(): use
audio_sample_rate.max(96_000) as the target rather than the hardcoded
96_000.  The two diverge when audio_sample_rate > 96_000, causing the
VdesDecoder to use the wrong symbol-to-sample ratio.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 10:14:09 +01:00
sjgandClaude Sonnet 4.6 a1bcf6f8bf [fix](trx-vdes): improve symbol timing and add burst CFO correction
Replace the free-running phase counter in slice_pi4_qpsk_symbols with
linear interpolation to sample the IQ stream at exact symbol epochs.
Add estimate_differential_cfo() that uses the 4th-power method to
cancel pi/4-QPSK modulation phase, yielding a per-burst CFO estimate
that is removed before differential decoding.

At the ~1.25 samples/symbol IQ rate produced by the current decimation
pipeline, a closed-loop Gardner or Mueller-Müller TED requires at least
2 SPS and cannot be applied; the open-loop linear interpolation is the
best achievable without restructuring the IQ tap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 10:14:00 +01:00
sjgandClaude Sonnet 4.6 0fc92bb1de [fix](trx-client): remove stale history_store.rs scaffold
History persistence lives in trx-server, not trx-client.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 10:13:49 +01:00
sjgandClaude Sonnet 4.6 2f1b0609fb [feat](trx-server): persist 24h decode history across restarts
Move persistent history from trx-client to trx-server where decode
events originate. History for AIS, VDES, APRS, CW, FT8, and WSPR is
loaded from ~/.local/cache/trx-rs/history.db at startup and flushed
to disk every 60 seconds. CW events are now also stored in
DecoderHistories and replayed to connecting clients, consistent with
all other decoder types.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 09:50:42 +01:00
sjgandClaude Sonnet 4.6 b65b85e13c [feat](trx-client): persist 24h decode history across restarts
Add pickledb-backed persistent history store for all decoder types
(AIS, VDES, APRS, CW, FT8, WSPR). History is loaded from
~/.local/cache/trx-rs/history.db at startup and flushed to disk
every 60 seconds. On load, entry timestamps are reconstructed from
stored Unix ms values so 24h pruning continues to work correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 09:43:48 +01:00
sjgandClaude Sonnet 4.6 1001786a08 [fix](trx-backend-soapysdr): ensure IQ stream recovery after overflow
Two problems prevented reliable recovery after a persistent overflow:

1. Restart storm: once read_error_streak >= 3, every subsequent read
   failure triggered a deactivate/activate cycle, potentially preventing
   the hardware from stabilising. Fix: after a successful restart, reset
   read_error_streak to 1 so the stream gets 2 more failures before the
   next restart attempt.

2. Stuck-deactivated stream: if activate() failed after overflow, the
   stream was left deactivated. Subsequent reads returned non-overflow
   errors which handle_read_error ignored (Ok(false)), so the stream was
   never reactivated. Fix: add a high-streak fallback (>= 10 consecutive
   errors of any kind) that also attempts a full deactivate/activate
   restart, covering the stuck-deactivated case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 09:31:17 +01:00
sjgandClaude Sonnet 4.6 bfc510e1eb [fix](trx-client,trx-server): fix spectrum death and stuck shutdown after IQ overflow
Two bugs triggered by a SoapySDR IQ overflow:

1. Spectrum dies permanently (trx-client): when GetSpectrum times out
   (300ms SPECTRUM_IO_TIMEOUT), the error was silently swallowed and
   the spectrum buffer cleared. The in-flight response remained in the
   TCP receive buffer, desynchronising all subsequent reads so every
   poll kept failing. Fix: propagate the error so handle_connection
   returns and the outer loop reconnects, restoring TCP sync.

2. CTRL+C hangs trx-server: after IQ overflow, the sdr-iq-read thread
   can get stuck in a blocking SoapySDR/USB call (deactivate/activate
   with no timeout). Tokio received SIGINT and aborted async tasks, but
   the process could not exit while the native thread was blocked in
   uninterruptible I/O. Fix: call std::process::exit(0) after the
   graceful shutdown sequence so the OS forcibly terminates all threads.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 09:25:08 +01:00
sjgandClaude Sonnet 4.6 e2c568a98a [fix](trx-frontend-http): async decode history replay to unblock UI
Server emits an SSE sentinel event (history_done) after replaying
stored history. Client buffers all incoming messages until the sentinel
arrives, then drains the buffer in 30-event chunks via setTimeout so
the browser can handle input between batches. Live events after the
sentinel are dispatched immediately as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-07 09:12:13 +01:00
sjgandClaude Sonnet 4.6 b23f05966f [fix](trx-frontend-http): show CW bar line as it decodes, not after flush
Prepend the in-progress line to the bar render so characters appear
immediately rather than waiting for a newline or 5s gap.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 22:33:02 +01:00
sjgandClaude Sonnet 4.6 90d446c8f4 [fix](trx-frontend-http): add cw-bar-overlay to bar overlay CSS selector
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 22:31:22 +01:00
sjgandClaude Sonnet 4.6 4272094882 [feat](trx-frontend-http): add CW live bar overlay
Show a live decode bar on the overview strip when in CW/CWR mode,
matching the APRS and AIS bar pattern. Accumulates decoded characters
into lines (split on newline events or >5s gaps), keeps a 15-minute
rolling history, and shows up to 8 recent lines with timestamp and
WPM/tone metadata. Clears on resetCwHistoryView.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 22:28:41 +01:00
sjgandClaude Sonnet 4.6 175abe35f9 [fix](trx-frontend-http): guard CW auto UI against concurrent SSE updates
Add cwAutoLocalOverride flag in cw.js to block server-state snapshots
from overriding the checkbox while a user-initiated POST is in-flight.
Expose applyCwAutoUiFromServer for app.js render() to call instead of
applyCwAutoUi, preventing a racing SSE event carrying the old cw_auto
value from immediately undoing the user's toggle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 22:07:05 +01:00
sjgandClaude Sonnet 4.6 91562b2a4b [fix](trx-cw): fix window size, dot/dash threshold, and cleanup
- Reduce analysis window from 50ms to 10ms so the decoder can detect
  dits at 25+ WPM (at 25 WPM a dit is 48ms, shorter than the old window)
- Fix dot/dash classification threshold from 2.0× to 1.5× unit_ms;
  ITU Morse dah = 3× dit, so the midpoint boundary is 1.5×
- Replace O(n) on_durations.remove(0) with drain() to trim the window
- Remove pointless emit_text() wrapper; callers now call emit_event()
  directly

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 21:30:58 +01:00
sjgandOpenAI Codex 4d22fa964d [feat](trx-frontend-http): show AIS tracks only for selection
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 17:29:12 +01:00
sjgandOpenAI Codex edaef98522 [feat](trx-frontend-http): show APRS tracks only for selection
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 17:11:04 +01:00
sjgandOpenAI Codex 7de847b504 [fix](trx-frontend-http): preserve APRS event timestamps
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 16:19:46 +01:00
sjgandOpenAI Codex faaaad6ab9 [fix](trx-frontend-http): defer decode SSE until plugins load
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 16:17:28 +01:00
sjgandOpenAI Codex 69b2aee753 [fix](trx-server): preserve decoder history timestamps
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 16:08:34 +01:00
sjgandOpenAI Codex e3378d5f49 [fix](trx-client): start decode collector before audio replay
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 16:01:31 +01:00
sjgandOpenAI Codex f9c0fa6981 [fix](trx-server): add rig task timeouts to avoid stalls
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 15:45:10 +01:00
sjgandOpenAI Codex ab27f111d5 [fix](trx-client): reconnect on remote poll timeouts
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 15:33:28 +01:00
sjgandOpenAI Codex 8c16f0da41 [fix](trx-frontend-http): preserve decoder history timestamps
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 11:58:07 +01:00
sjgandOpenAI Codex 18d3a00c07 [fix](trx-server): optimize replay and stamp APRS history time
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 11:58:02 +01:00
sjgandOpenAI Codex e5b9fb7aca [refactor](trx-core): add buffered audio write helper
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-06 11:57:55 +01:00
sjgandOpenAI Codex 3d0cdbd181 [docs](trx-rs): document SoapySDR squelch settings
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 22:43:32 +01:00
sjgandOpenAI Codex 890abcdc24 [feat](trx-frontend-http): add SQL slider and spectrum screenshot hotkey
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 22:43:28 +01:00
sjgandOpenAI Codex 8bd779a239 [feat](trx-server): wire SDR squelch through server config and rig task
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 22:43:23 +01:00
sjgandOpenAI Codex 3eb5a615b9 [feat](trx-backend-soapysdr): extend squelch and boost high denoise
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 22:43:19 +01:00
sjgandOpenAI Codex 3188c9b0ad [feat](trx-protocol): add SDR squelch command mapping
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 22:43:13 +01:00
sjgandOpenAI Codex 5597a8c206 [feat](trx-core): add SDR squelch command and state fields
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 22:43:09 +01:00
sjg 3d9003feb2 [feat](trx-server): add per-rig enable switch in multi-rig config
Add [[rigs]].enable (default true) and skip disabled rigs during\nresolution/uniqueness checks.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 22:15:45 +01:00
sjgandOpenAI Codex 3f2892e245 [fix](trx-frontend-http): match waterfall BW resize behavior to waveform
Enable BW edge drag initiation on overview/waterfall canvas and align drag/click suppression behavior with waveform interactions.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 22:10:49 +01:00
sjg 5dcc117e61 [fix](trx-backend-soapysdr): disable hidden AIS DSP outside AIS modes
Add per-channel processing gating and disable hidden AIS channel DSP unless mode is AIS or MARINE, reducing continuous IQ read-loop CPU load in normal operation.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 22:01:21 +01:00
sjg 9ed93ec0fa [feat](trx-frontend-http): align waterfall click and restore bookmark marker lines
Add click-to-tune behavior on overview waterfall matching spectrum interactions, restore bookmark marker lines in the overlay using category colors, and keep current-tuned frequency marker visually distinct.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 21:56:19 +01:00
sjg 8be3b273bc [fix](trx-backend-soapysdr): reduce sdr-iq-read CPU spin on idle reads
Skip IQ fanout buffer cloning when no subscribers exist and apply backoff on repeated zero-length reads to avoid hot-loop CPU spikes.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 21:50:17 +01:00
sjg 4e6a800391 [fix](trx-frontend-http): fix waterfall updates and bookmark top anchoring
Ensure overview waterfall incremental updates continue on HiDPI and anchor bookmark chips to the top of the full spectrum view (waterfall + waveform).\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 21:45:49 +01:00
sjg c4f0844137 [fix](trx-frontend-http): optimize WebGL rendering and pin bookmarks to top
Improve WebGL runtime performance by caching/downsampling overview waterfall texture updates and batching marker/dashed-line draws; keep bookmark chips anchored at the top of the waterfall area.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 21:41:49 +01:00
sjg 27b90a62c5 [feat](trx-frontend-http): migrate frontend canvas rendering to WebGL
Replace Canvas2D rendering in spectrum, overview, signal overlay, and CW tone picker with a shared WebGL renderer and wire the new asset into frontend HTTP routes.\n\nCo-authored-by: OpenAI Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 21:37:50 +01:00
sjg 633ad92dd6 [fix](trx-frontend-http): decouple signal view from spectrum and fix canvas scaling 2026-03-05 21:14:35 +01:00
sjg a041dd4505 [fix](trx-backend-ft817): bound lock/unlock reads to prevent set_mode timeout 2026-03-05 20:44:32 +01:00
sjg ccef359034 [fix](trx): speed up web load and harden FT817/Soapy recovery 2026-03-05 20:36:46 +01:00
sjg bc0d9a6273 [fix](ftx): treat second callsign as source in directed traffic 2026-03-05 20:23:22 +01:00
sjg bf74044c05 [fix](trx): normalize FT8 history freq and add map locator links 2026-03-05 19:48:20 +01:00
sjg 8e8d21b527 [feat](trx-frontend): add longer peak hold durations 2026-03-05 19:34:17 +01:00
sjg 1370234b35 [style](trx-frontend): make signal split slider narrower 2026-03-05 19:33:29 +01:00
sjg 49f44e84a0 [fix](trx): ignore FTx farewell pseudo-locators and narrow split slider 2026-03-05 19:24:54 +01:00
sjg 05e72e21e8 [feat](trx-frontend): reset signal split on slider double-click 2026-03-05 18:34:59 +01:00
sjg 2e6b9f87fb [fix](trx-frontend): compact split slider and center side controls 2026-03-05 18:28:42 +01:00
sjg 083d009aa5 [feat](trx-frontend): add signal split slider and align spectrum side controls
Add a right-side slider to control the waterfall/waveform split and\npersist the selected ratio locally.\n\nRework spectrum height layout so manual resize adjusts total plot height\nwhile split controls the overview/spectrum ratio.\n\nKeep center-frequency arrows and side bookmark stacks vertically centered\nwithin the full spectrum view container.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 18:17:34 +01:00
sjg 4c69e2bcde [fix](trx-frontend): improve spectrum resize interaction
Make the spectrum resize grip easier to use and style it closer to\nexisting controls.\n\nKeep auto-max behavior by default while allowing manual drag to\nresize beyond viewport fill, enforcing only the minimum height.\n\nCo-authored-by: Codex <codex@openai.com>

Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 18:08:16 +01:00
sjgandCodex a905fa9678 [fix](trx-frontend): maximize spectrum viewport and add resize grip
Make spectrum plot use maximum available viewport height by default.
Add draggable vertical resize grip with a reasonable minimum height
and double-click reset back to auto-max.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-05 17:45:50 +01:00
sjgandCodex bfff095cf0 [fix](trx-core): auto-enable CW decode on CW/CWR mode
When mode is set to CW/CWR, force cw_decode_enabled=true in state
application to avoid stale disabled decode state.
Also route initial mode setup through apply_mode.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 23:17:44 +01:00
sjgandCodex 14d58ce989 [fix](trx-server): hard-gate CW decode to CW/CWR modes
Enforce CW decode processing only when mode is CW/CWR and decoder
is enabled, even within the receive loop, and remove CW path RMS
zero-gating to preserve weak tone decoding.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 23:14:23 +01:00
sjgandCodex 75e177a5f4 [fix](trx-core): enable CW decoder by default
Set cw_decode_enabled default to true so CW decoding can start
without an unavailable UI toggle.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 23:14:14 +01:00
sjgandCodex 9786030f7d [fix](trx-cw): stabilize auto tone scan window
Keep manual CW tone setting range at 100-10000 Hz, but limit auto-tone
scanning to 300-1200 Hz to avoid locking onto high-frequency noise.
Retain Nyquist-safe upper clamping.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 23:09:07 +01:00
sjgandCodex c1f37a320f [fix](trx-cw): widen tone scan range and clamp by Nyquist
Expand CW decoder tone scan/control range to 100-10000 Hz and cap the
upper bound by sample-rate Nyquist to keep detection stable.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 23:05:10 +01:00
sjgandCodex f3f0b1dfd3 [fix](trx-server): accept CW tone range up to 10 kHz
Expand server-side CW tone command clamping to 100-10000 Hz to match
frontend controls and picker behavior.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 23:05:03 +01:00
sjgandCodex d8f7ebafa0 [fix](trx-frontend): fix CW picker visibility and widen tone range
Fix CW picker redraw when the decoder sub-tab becomes visible to avoid
white/blank canvas rendering.
Widen CW tone picker/input range to 100-10000 Hz and raise CW/CWR
bandwidth max to 9 kHz.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 23:04:56 +01:00
sjgandCodex 878b50cad7 [fix](trx-server): gate near-silent audio before decode
Apply an RMS gate to near-silent decoder input frames and zero them
before APRS/CW/FT8/WSPR processing to avoid false decodes from
unsquelched/no-signal noise.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 22:58:02 +01:00
sjgandCodex 239857d536 [fix](trx-frontend): restore CW picker rendering across spectrum edges
Remove CW tone-window clipping to current spectrum edge coverage so
the picker always renders the audio range and does not blank out.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 22:53:31 +01:00
sjgandCodex 4f01db0801 [fix](trx-frontend): render CW picker as audio spectrum trace
Render the CW tone picker as an audio-frequency spectrum trace with grid,
line and filled area instead of a normalized gradient wash.
Keep exact click-to-tone selection and marker behavior.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 22:49:52 +01:00
sjgandCodex 1ebe65e0f2 [fix](trx-frontend): fix CW audio picker and bookmark add button
Use an audio-window tone picker for CW with exact click-to-tone mapping.
Make + Add Bookmark inherit the shared button style.

Co-authored-by: Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 22:46:08 +01:00
sjgandOpenAI Codex 2a9cd5ed0e [fix](trx-frontend): add decoder pause controls and rename tab
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 22:37:26 +01:00
sjgandOpenAI Codex eac5e142db [fix](trx-frontend): rework cw auto and tone picker behavior
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 22:31:08 +01:00
sjgandOpenAI Codex d6ad873bfe [fix](trx-frontend): retune center after bw edge drag
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 22:25:39 +01:00
sjgandOpenAI Codex 0175b1c916 [feat](trx-frontend): add map search filter
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 22:17:55 +01:00
sjgandOpenAI Codex a45979fe9b [fix](trx-frontend): default map sources to hide bookmarks
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 20:04:39 +01:00
sjgandOpenAI Codex e91d36775b [fix](trx-frontend): align band chip colors with locator overlays
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 20:00:33 +01:00
sjgandOpenAI Codex 4b9e84e194 [fix](trx-frontend): refine map locator styling
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:55:37 +01:00
sjgandOpenAI Codex 013667f284 [fix](trx-frontend): align bw resize with one-sided filters
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:49:44 +01:00
sjgandOpenAI Codex 0836091bbc [fix](trx-client): preserve ft8 history on reload
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:45:17 +01:00
sjgandOpenAI Codex 8b174db04d [feat](trx-frontend): add map fullscreen toggle
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:37:38 +01:00
sjgandOpenAI Codex 125237f53d [fix](trx-frontend): tighten map sizing and path theming
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:32:01 +01:00
sjgandOpenAI Codex fbfff4154f [fix](trx-frontend): compact map tooltip frequencies
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:26:48 +01:00
sjgandOpenAI Codex c34ecc493d [fix](trx-frontend): refine map source and popup states
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:22:32 +01:00
sjgandOpenAI Codex 9e1bdf2435 [fix](trx-frontend): refine map popup rendering
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:17:36 +01:00
sjgandOpenAI Codex 75a74d4063 [fix](trx-frontend): render one-sided bw for ssb modes
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:12:32 +01:00
sjgandOpenAI Codex 283125989b [fix](trx-frontend): animate selected locator paths
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 19:02:31 +01:00
sjgandOpenAI Codex d1968bd2ba [fix](trx-frontend): tighten bookmark and map filter overflow
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-04 18:55:26 +01:00
sjgandOpenAI Codex 046d0a33af [fix](trx-frontend): gate cw status by rig mode
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-03 22:41:39 +01:00
sjgandOpenAI Codex bd5c909695 [fix](trx-frontend): polish map filter layout
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-03 22:37:05 +01:00
sjgandOpenAI Codex a194043caf [fix](trx-frontend): unify map source filters
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-03 22:31:44 +01:00
sjgandOpenAI Codex 52bf573e4e [fix](trx-frontend): snap locator bands to nearest ham band
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-03 22:24:21 +01:00
sjgandOpenAI Codex efe9dc346b [fix](trx-frontend): make locator filters two-phase
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-03 22:20:38 +01:00
sjgandOpenAI Codex df173a3202 [fix](trx-frontend): make locator details click-only
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-03 22:17:34 +01:00
sjgandOpenAI Codex 4bdb4937c9 [fix](trx-frontend): replace locator wavelength filters with bands
Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
2026-03-03 22:12:27 +01:00