From 77c9b52ac305f13efbb3f7f020d035eecdd1df2e Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Sat, 4 Apr 2026 21:35:02 +0200 Subject: [PATCH] [feat](trx-server): run fast S-meter tick on CAT rigs too Extend the between-poll meter refresh that was previously SDR-only to also run on CAT backends. CAT rigs now poll the S-meter every 150 ms (SDR remains at 100 ms), so the frontend bar moves in near real-time instead of updating only on the 500 ms full-state poll. The fast path calls get_signal_strength_db() first (SDR), then falls back to the coarse get_signal_strength() + map_signal_strength path for CAT rigs. It is skipped while powered off, transmitting, or while a full poll is paused after a CAT write. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/trx-server/src/rig_task.rs | 38 +++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/trx-server/src/rig_task.rs b/src/trx-server/src/rig_task.rs index b7c63cb..d565688 100644 --- a/src/trx-server/src/rig_task.rs +++ b/src/trx-server/src/rig_task.rs @@ -254,17 +254,18 @@ pub async fn run_rig_task( ); let _ = state_tx.send(state.clone()); - // SDR backends can refresh signal strength cheaply (cached DSP value), - // so we run a fast meter tick between full polls to keep the S-meter - // responsive — matching the spectrum redraw rate (~100 ms). + // Run a fast meter tick between full polls to keep the S-meter + // responsive. SDR backends expose a cached DSP reading and can + // refresh every 100 ms; CAT rigs poll the serial link, which is + // slower but still fine at ~150 ms. let is_sdr = rig.as_sdr_ref().is_some(); - let meter_tick_duration = Duration::from_millis(100); - let mut meter_tick: std::pin::Pin> = if is_sdr { - Box::pin(tokio::time::sleep(meter_tick_duration)) + let meter_tick_duration = if is_sdr { + Duration::from_millis(100) } else { - // Park indefinitely for non-SDR backends; the branch will never fire. - Box::pin(tokio::time::sleep(Duration::from_secs(86400))) + Duration::from_millis(150) }; + let mut meter_tick: std::pin::Pin> = + Box::pin(tokio::time::sleep(meter_tick_duration)); // Main task loop let mut current_poll_duration = polling.interval(state.status.tx_en); @@ -289,11 +290,24 @@ pub async fn run_rig_task( Err(_) => break, } } - // Fast meter-only refresh for SDR backends (cheap cached read). - _ = &mut meter_tick, if is_sdr => { + // Fast meter-only refresh between full polls. + _ = &mut meter_tick => { meter_tick = Box::pin(tokio::time::sleep(meter_tick_duration)); - if !matches!(state.control.enabled, Some(false)) { - if let Some(db) = rig.get_signal_strength_db().await { + // Skip while powered off, transmitting, or while a + // full poll is paused (typically just after a CAT write). + let powered_off = matches!(state.control.enabled, Some(false)); + let paused = poll_pause_until + .map(|u| Instant::now() < u) + .unwrap_or(false); + if !powered_off && !state.status.tx_en && !paused { + let new_sig = if let Some(db) = rig.get_signal_strength_db().await { + Some(db) + } else if let Ok(meter) = rig.get_signal_strength().await { + Some(map_signal_strength(&state.status.mode, meter)) + } else { + None + }; + if let Some(db) = new_sig { let prev = state.status.rx.as_ref().and_then(|r| r.sig); if prev != Some(db) { state.status.rx.get_or_insert(RigRxStatus { sig: None }).sig = Some(db);