[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) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 21:35:02 +02:00
parent bb45153ede
commit 77c9b52ac3
+26 -12
View File
@@ -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<Box<tokio::time::Sleep>> = 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<tokio::time::Sleep>> =
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);