From 19ab3b3931ac9ab51d3a25ac33e608bb2dc5ffa3 Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Wed, 11 Mar 2026 20:58:20 +0100 Subject: [PATCH] [feat](trx-rs): remove MARINE mode (superseded by virtual channels) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MARINE was a composite mode that ran both AIS and VDES decoders simultaneously. It is now fully replaced by allocating two virtual channels — one tuned to the AIS frequencies and one to VDES — each decoded independently. - trx-core/state: remove RigMode::MARINE variant - trx-protocol/codec: remove MARINE parse/serialize - trx-backend-ft817: remove MARINE from unsupported-mode guard - trx-backend-ft450d: remove MARINE from FM CAT code mapping - trx-backend-soapysdr: remove MARINE from bandwidth table, supported modes list, AIS channel activity check, parse_rig_mode, vchan_impl bandwidth table, demod selection, dsp/channel bandwidth / sample-rate / IQ-tap guards - trx-server/audio: remove MARINE from AIS and VDES decoder activation - trx-server/rig_task: remove MARINE from audio-streaming mode list - trx-server/main: remove MARINE from bandwidth table, mode parser, VDES channel subscription match - app.js: remove isMarineMode(), MARINE entry in MODE_BW_SPECS, MARINE bandwidth specs block in visibleBandwidthSpecs(), MARINE from decoder status mode lists, MARINE BW-edge drag guard Co-Authored-By: Claude Sonnet 4.6 Signed-off-by: Stan Grams --- .../trx-frontend-http/assets/web/app.js | 22 +++++-------------- src/trx-core/src/rig/state.rs | 1 - src/trx-protocol/src/codec.rs | 2 -- src/trx-server/src/audio.rs | 16 +++++++------- src/trx-server/src/main.rs | 5 ++--- src/trx-server/src/rig_task.rs | 2 +- .../trx-backend/trx-backend-ft450d/src/lib.rs | 2 +- .../trx-backend/trx-backend-ft817/src/lib.rs | 2 +- .../trx-backend-soapysdr/src/demod.rs | 2 +- .../trx-backend-soapysdr/src/dsp/channel.rs | 6 ++--- .../trx-backend-soapysdr/src/lib.rs | 5 ++--- .../trx-backend-soapysdr/src/vchan_impl.rs | 2 +- 12 files changed, 25 insertions(+), 42 deletions(-) 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 f16810b..a2ab36f 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 @@ -1329,20 +1329,9 @@ function isVdesMode(mode = modeEl ? modeEl.value : "") { return String(mode || "").toUpperCase() === "VDES"; } -function isMarineMode(mode = modeEl ? modeEl.value : "") { - return String(mode || "").toUpperCase() === "MARINE"; -} - function visibleBandwidthSpecs(freqHz = lastFreqHz, mode = modeEl ? modeEl.value : "") { if (!Number.isFinite(freqHz)) return []; const modeUpper = String(mode || "").toUpperCase(); - if (modeUpper === "MARINE") { - return [ - { centerHz: freqHz - 137_500, widthHz: 100_000 }, - { centerHz: freqHz, widthHz: 12_500 }, - { centerHz: freqHz + 50_000, widthHz: 12_500 }, - ]; - } if (modeUpper === "AIS") { return [ { centerHz: freqHz, widthHz: currentBandwidthHz }, @@ -2478,14 +2467,14 @@ function render(update) { const wsprStatus = document.getElementById("wspr-status"); setModeBoundDecodeStatus( aisStatus, - ["AIS", "MARINE"], + ["AIS"], "Select AIS mode to decode", "Connected, listening for packets", ); if (window.updateAisBar) window.updateAisBar(); setModeBoundDecodeStatus( vdesStatus, - ["VDES", "MARINE"], + ["VDES"], "Select VDES mode to decode", "Connected, listening for bursts", ); @@ -3224,7 +3213,6 @@ const MODE_BW_DEFAULTS = { FM: [12_500, 2_500, 25_000, 500], AIS: [25_000, 12_500, 50_000, 500], VDES: [100_000, 25_000, 200_000, 1_000], - MARINE: [100_000, 12_500, 100_000, 500], WFM: [180_000, 50_000,300_000,5_000], DIG: [3_000, 300, 6_000, 100], PKT: [25_000, 300, 50_000, 500], @@ -6212,9 +6200,9 @@ function updateDecodeStatus(text) { const aprs = document.getElementById("aprs-status"); const cw = document.getElementById("cw-status"); const ft8 = document.getElementById("ft8-status"); - setModeBoundDecodeStatus(ais, ["AIS", "MARINE"], "Select AIS mode to decode", text); + setModeBoundDecodeStatus(ais, ["AIS"], "Select AIS mode to decode", text); const vdesText = text === "Connected, listening for packets" ? "Connected, listening for bursts" : text; - setModeBoundDecodeStatus(vdes, ["VDES", "MARINE"], "Select VDES mode to decode", vdesText); + setModeBoundDecodeStatus(vdes, ["VDES"], "Select VDES mode to decode", vdesText); setModeBoundDecodeStatus(aprs, ["PKT"], "Select PKT mode to decode", text); const cwText = text === "Connected, listening for packets" ? "Connected, listening for CW" : text; setModeBoundDecodeStatus(cw, ["CW", "CWR"], "Select CW mode to decode", cwText); @@ -7670,7 +7658,7 @@ if (overviewCanvas) { // ── BW strip edge hit-test (CSS pixels) ────────────────────────────────────── function getBwEdgeHit(cssX, cssW, range) { if (!lastFreqHz || !currentBandwidthHz || !lastSpectrumData) return null; - if (isMarineMode()) return null; + const HIT = 8; let bestEdge = null; let bestDist = Number.POSITIVE_INFINITY; diff --git a/src/trx-core/src/rig/state.rs b/src/trx-core/src/rig/state.rs index 1bf3fb3..47f6c64 100644 --- a/src/trx-core/src/rig/state.rs +++ b/src/trx-core/src/rig/state.rs @@ -76,7 +76,6 @@ pub enum RigMode { FM, AIS, VDES, - MARINE, DIG, PKT, Other(String), diff --git a/src/trx-protocol/src/codec.rs b/src/trx-protocol/src/codec.rs index 659b289..88fc62a 100644 --- a/src/trx-protocol/src/codec.rs +++ b/src/trx-protocol/src/codec.rs @@ -24,7 +24,6 @@ pub fn parse_mode(s: &str) -> RigMode { "WFM" => RigMode::WFM, "AIS" => RigMode::AIS, "VDES" => RigMode::VDES, - "MARINE" => RigMode::MARINE, "DIG" | "DIGI" => RigMode::DIG, "PKT" | "PACKET" => RigMode::PKT, other => RigMode::Other(other.to_string()), @@ -46,7 +45,6 @@ pub fn mode_to_string(mode: &RigMode) -> String { RigMode::WFM => "WFM".to_string(), RigMode::AIS => "AIS".to_string(), RigMode::VDES => "VDES".to_string(), - RigMode::MARINE => "MARINE".to_string(), RigMode::DIG => "DIG".to_string(), RigMode::PKT => "PKT".to_string(), RigMode::Other(s) => s.clone(), diff --git a/src/trx-server/src/audio.rs b/src/trx-server/src/audio.rs index c4f7a37..345e8bd 100644 --- a/src/trx-server/src/audio.rs +++ b/src/trx-server/src/audio.rs @@ -1102,7 +1102,7 @@ fn downmix_if_needed(frame: Vec, channels: u16) -> Vec { mono } -/// Run the AIS decoder task. Only processes PCM when rig mode is AIS or MARINE. +/// Run the AIS decoder task. Only processes PCM when rig mode is AIS. pub async fn run_ais_decoder( sample_rate: u32, channels: u16, @@ -1118,7 +1118,7 @@ pub async fn run_ais_decoder( let mut was_active = false; let mut active = matches!( state_rx.borrow().status.mode, - RigMode::AIS | RigMode::MARINE + RigMode::AIS ); loop { @@ -1126,7 +1126,7 @@ pub async fn run_ais_decoder( match state_rx.changed().await { Ok(()) => { let state = state_rx.borrow(); - active = matches!(state.status.mode, RigMode::AIS | RigMode::MARINE); + active = matches!(state.status.mode, RigMode::AIS); if active { pcm_a_rx = pcm_a_rx.resubscribe(); pcm_b_rx = pcm_b_rx.resubscribe(); @@ -1178,7 +1178,7 @@ pub async fn run_ais_decoder( match changed { Ok(()) => { let state = state_rx.borrow(); - active = matches!(state.status.mode, RigMode::AIS | RigMode::MARINE); + active = matches!(state.status.mode, RigMode::AIS); if !active && was_active { decoder_a.reset(); decoder_b.reset(); @@ -1196,7 +1196,7 @@ pub async fn run_ais_decoder( } } -/// Run the VDES decoder task. Only processes IQ when rig mode is VDES or MARINE. +/// Run the VDES decoder task. Only processes IQ when rig mode is VDES. pub async fn run_vdes_decoder( sample_rate: u32, mut iq_rx: broadcast::Receiver>>, @@ -1209,7 +1209,7 @@ pub async fn run_vdes_decoder( let mut was_active = false; let mut active = matches!( state_rx.borrow().status.mode, - RigMode::VDES | RigMode::MARINE + RigMode::VDES ); loop { @@ -1217,7 +1217,7 @@ pub async fn run_vdes_decoder( match state_rx.changed().await { Ok(()) => { let state = state_rx.borrow(); - active = matches!(state.status.mode, RigMode::VDES | RigMode::MARINE); + active = matches!(state.status.mode, RigMode::VDES); if active { iq_rx = iq_rx.resubscribe(); } @@ -1250,7 +1250,7 @@ pub async fn run_vdes_decoder( match changed { Ok(()) => { let state = state_rx.borrow(); - active = matches!(state.status.mode, RigMode::VDES | RigMode::MARINE); + active = matches!(state.status.mode, RigMode::VDES); if !active && was_active { decoder.reset(); was_active = false; diff --git a/src/trx-server/src/main.rs b/src/trx-server/src/main.rs index f145dcf..997c46a 100644 --- a/src/trx-server/src/main.rs +++ b/src/trx-server/src/main.rs @@ -246,7 +246,7 @@ fn default_audio_bandwidth_for_mode(mode: &trx_core::rig::state::RigMode) -> u32 RigMode::FM => 12_500, RigMode::WFM => 180_000, RigMode::AIS => 25_000, - RigMode::VDES | RigMode::MARINE => 100_000, + RigMode::VDES => 100_000, RigMode::Other(_) => 3_000, } } @@ -269,7 +269,6 @@ fn parse_rig_mode( "FM" => RigMode::FM, "AIS" => RigMode::AIS, "VDES" => RigMode::VDES, - "MARINE" => RigMode::MARINE, "DIG" => RigMode::DIG, "PKT" => RigMode::PKT, _ => initial_mode.clone(), @@ -362,7 +361,7 @@ fn build_sdr_rig_from_instance(rig_cfg: &RigInstanceConfig) -> SdrRigBuildResult // explicit VDES channel has been configured. let vdes_channel_idx = channels .iter() - .position(|(_, mode, _, _)| matches!(mode, trx_core::rig::state::RigMode::VDES | trx_core::rig::state::RigMode::MARINE)) + .position(|(_, mode, _, _)| matches!(mode, trx_core::rig::state::RigMode::VDES)) .unwrap_or(0); let vdes_iq = sdr_rig.subscribe_iq_channel(vdes_channel_idx); // Extract the virtual channel manager before the rig is consumed by Box. diff --git a/src/trx-server/src/rig_task.rs b/src/trx-server/src/rig_task.rs index ecf161f..a2afba7 100644 --- a/src/trx-server/src/rig_task.rs +++ b/src/trx-server/src/rig_task.rs @@ -845,7 +845,7 @@ fn map_signal_strength(mode: &RigMode, raw: u8) -> i32 { // FT-817 returns 0-15 for signal strength // Map to approximate dBm / S-units match mode { - RigMode::FM | RigMode::WFM | RigMode::AIS | RigMode::VDES | RigMode::MARINE => { + RigMode::FM | RigMode::WFM | RigMode::AIS | RigMode::VDES => { -120 + (raw as i32 * 6) } _ => -127 + (raw as i32 * 6), diff --git a/src/trx-server/trx-backend/trx-backend-ft450d/src/lib.rs b/src/trx-server/trx-backend/trx-backend-ft450d/src/lib.rs index 02009c6..e7d612e 100644 --- a/src/trx-server/trx-backend/trx-backend-ft450d/src/lib.rs +++ b/src/trx-server/trx-backend/trx-backend-ft450d/src/lib.rs @@ -513,7 +513,7 @@ fn encode_mode(mode: &RigMode) -> DynResult { RigMode::USB => Ok('2'), RigMode::CW => Ok('3'), RigMode::FM => Ok('4'), - RigMode::AIS | RigMode::VDES | RigMode::MARINE => Ok('4'), + RigMode::AIS | RigMode::VDES => Ok('4'), RigMode::AM => Ok('5'), RigMode::DIG => Ok('6'), RigMode::CWR => Ok('7'), diff --git a/src/trx-server/trx-backend/trx-backend-ft817/src/lib.rs b/src/trx-server/trx-backend/trx-backend-ft817/src/lib.rs index 3f5018d..8777971 100644 --- a/src/trx-server/trx-backend/trx-backend-ft817/src/lib.rs +++ b/src/trx-server/trx-backend/trx-backend-ft817/src/lib.rs @@ -603,7 +603,7 @@ fn encode_mode(mode: &RigMode) -> Option { RigMode::FM => 0x08, RigMode::DIG => 0x0A, RigMode::PKT => 0x0C, - RigMode::AIS | RigMode::VDES | RigMode::MARINE | RigMode::Other(_) => return None, + RigMode::AIS | RigMode::VDES | RigMode::Other(_) => return None, }) } diff --git a/src/trx-server/trx-backend/trx-backend-soapysdr/src/demod.rs b/src/trx-server/trx-backend/trx-backend-soapysdr/src/demod.rs index d6796fd..1aeb3c4 100644 --- a/src/trx-server/trx-backend/trx-backend-soapysdr/src/demod.rs +++ b/src/trx-server/trx-backend/trx-backend-soapysdr/src/demod.rs @@ -156,7 +156,7 @@ impl Demodulator { RigMode::AM => Self::Am, RigMode::FM => Self::Fm, RigMode::WFM => Self::Wfm, - RigMode::AIS | RigMode::VDES | RigMode::MARINE => Self::Fm, + RigMode::AIS | RigMode::VDES => Self::Fm, RigMode::CW | RigMode::CWR => Self::Cw, RigMode::DIG => Self::Passthrough, // VHF/UHF packet radio (APRS, AX.25) is FM-encoded AFSK. diff --git a/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp/channel.rs b/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp/channel.rs index 87d696c..a084786 100644 --- a/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp/channel.rs +++ b/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp/channel.rs @@ -127,7 +127,7 @@ fn default_bandwidth_for_mode(mode: &RigMode) -> u32 { RigMode::FM => 12_500, RigMode::WFM => 180_000, RigMode::AIS => 25_000, - RigMode::VDES | RigMode::MARINE => 100_000, + RigMode::VDES => 100_000, RigMode::Other(_) => 3_000, } } @@ -199,7 +199,7 @@ impl ChannelDsp { let target_rate = match mode { RigMode::WFM => audio_bandwidth_hz.max(audio_sample_rate.saturating_mul(4)), - RigMode::VDES | RigMode::MARINE => audio_sample_rate.max(96_000), + RigMode::VDES => audio_sample_rate.max(96_000), _ => audio_sample_rate.max(1), }; let decim_factor = (sdr_sample_rate / target_rate.max(1)).max(1) as usize; @@ -466,7 +466,7 @@ impl ChannelDsp { self.scratch_decimated .reserve(capacity - self.scratch_decimated.capacity()); } - if matches!(self.mode, RigMode::VDES | RigMode::MARINE) && self.iq_tx.receiver_count() > 0 { + if matches!(self.mode, RigMode::VDES) && self.iq_tx.receiver_count() > 0 { self.scratch_iq_tap.clear(); if self.scratch_iq_tap.capacity() < capacity { self.scratch_iq_tap diff --git a/src/trx-server/trx-backend/trx-backend-soapysdr/src/lib.rs b/src/trx-server/trx-backend/trx-backend-soapysdr/src/lib.rs index dedb1c1..8af9281 100644 --- a/src/trx-server/trx-backend/trx-backend-soapysdr/src/lib.rs +++ b/src/trx-server/trx-backend/trx-backend-soapysdr/src/lib.rs @@ -68,7 +68,7 @@ impl SoapySdrRig { match mode { RigMode::LSB | RigMode::USB | RigMode::DIG => 3_000, RigMode::PKT | RigMode::AIS => 25_000, - RigMode::VDES | RigMode::MARINE => 100_000, + RigMode::VDES => 100_000, RigMode::CW | RigMode::CWR => 500, RigMode::AM => 9_000, RigMode::FM => 12_500, @@ -229,7 +229,6 @@ impl SoapySdrRig { RigMode::FM, RigMode::AIS, RigMode::VDES, - RigMode::MARINE, RigMode::DIG, RigMode::PKT, ], @@ -367,7 +366,7 @@ impl SoapySdrRig { let Some((ais_a_idx, ais_b_idx)) = self.ais_channel_indices else { return; }; - let enabled = matches!(self.mode, RigMode::AIS | RigMode::MARINE); + let enabled = matches!(self.mode, RigMode::AIS); let dsps = self.pipeline.channel_dsps.read().unwrap(); for idx in [ais_a_idx, ais_b_idx] { if let Some(dsp_arc) = dsps.get(idx) { diff --git a/src/trx-server/trx-backend/trx-backend-soapysdr/src/vchan_impl.rs b/src/trx-server/trx-backend/trx-backend-soapysdr/src/vchan_impl.rs index f133530..2a790e3 100644 --- a/src/trx-server/trx-backend/trx-backend-soapysdr/src/vchan_impl.rs +++ b/src/trx-server/trx-backend/trx-backend-soapysdr/src/vchan_impl.rs @@ -48,7 +48,7 @@ fn default_bandwidth_hz(mode: &RigMode) -> u32 { RigMode::FM => 12_500, RigMode::WFM => 180_000, RigMode::PKT | RigMode::AIS => 25_000, - RigMode::VDES | RigMode::MARINE => 100_000, + RigMode::VDES => 100_000, RigMode::Other(_) => 3_000, } }