From 9fe293e056d0068a87a03efb737635cc387b2142 Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Tue, 3 Mar 2026 01:01:00 +0100 Subject: [PATCH] [feat](trx-rs): expose marine mode and ft8 live bar Add an FT8 live overlay bar, align APRS top controls with the other decoder tabs, advertise MARINE in the SoapySDR mode list, and make the VDES decoder emit raw unsynced diagnostic frames instead of dropping weak bursts outright. Co-authored-by: OpenAI Codex Signed-off-by: Stanislaw Grams --- src/decoders/trx-vdes/src/lib.rs | 23 +++++++--- .../trx-frontend-http/assets/web/app.js | 1 + .../trx-frontend-http/assets/web/index.html | 3 +- .../assets/web/plugins/ft8.js | 45 +++++++++++++++++++ .../trx-frontend-http/assets/web/style.css | 19 +------- .../trx-backend-soapysdr/src/lib.rs | 1 + 6 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/decoders/trx-vdes/src/lib.rs b/src/decoders/trx-vdes/src/lib.rs index 19b9918..b73874b 100644 --- a/src/decoders/trx-vdes/src/lib.rs +++ b/src/decoders/trx-vdes/src/lib.rs @@ -118,7 +118,7 @@ impl VdesDecoder { return None; } - let framed = extract_candidate_frame(&symbols)?; + let framed = extract_candidate_frame(&symbols).unwrap_or_else(|| fallback_frame_slice(&symbols)); let rms = burst_rms(&samples); let mode = classify_vdes_burst(framed.symbols.len()); let payload_symbols = framed.payload_symbols(); @@ -129,7 +129,7 @@ impl VdesDecoder { &framed, &mode, rms, - &deinterleaved, + &framed.symbols, )); } @@ -143,7 +143,7 @@ impl VdesDecoder { &framed, &mode, rms, - &deinterleaved, + &framed.symbols, )); } let parsed = parse_vdes_payload(&decoded_bits); @@ -345,14 +345,25 @@ fn extract_candidate_frame(symbols: &[u8]) -> Option { }) } +fn fallback_frame_slice(symbols: &[u8]) -> FrameSlice { + let take = symbols.len().min(TER_MCS1_100_BURST_SYMBOLS); + FrameSlice { + start_offset: 0, + sync_score: 0.0, + sync_errors: (TER_MCS1_100_SYNC_SYMBOLS * 2) as u8, + phase_rotation: 0, + symbols: symbols[..take].to_vec(), + } +} + fn build_unsynced_message( channel: &str, framed: &FrameSlice, mode: &BurstMode<'_>, rms: f32, - deinterleaved: &[u8], + raw_symbols: &[u8], ) -> VdesMessage { - let raw_bytes = pack_dibits_msb(deinterleaved); + let raw_bytes = pack_dibits_msb(raw_symbols); let sync_pct = framed.sync_score * 100.0; VdesMessage { ts_ms: None, @@ -361,7 +372,7 @@ fn build_unsynced_message( repeat: 0, mmsi: 0, crc_ok: false, - bit_len: deinterleaved.len() * 2, + bit_len: raw_symbols.len() * 2, raw_bytes, lat: None, lon: None, diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js index 3f33f29..a7738b1 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js @@ -2062,6 +2062,7 @@ function render(update) { "Connected, listening for packets", ); if (window.updateAprsBar) window.updateAprsBar(); + if (window.updateFt8Bar) window.updateFt8Bar(); if (cwStatus && modeUpper !== "CW" && modeUpper !== "CWR" && cwStatus.textContent === "Receiving") { cwStatus.textContent = "Connected, listening for packets"; } diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html index 3e20909..d67e20b 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html @@ -81,6 +81,7 @@
+
@@ -473,7 +474,7 @@