From fc080f3719f22d8250ce4ee982e86c10dc3c7b2d Mon Sep 17 00:00:00 2001 From: rouggy Date: Sun, 30 Aug 2026 02:43:43 +0200 Subject: [PATCH] fix(icom): kill the leftover waveform in both command forms, and say so MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The blind kill at connect still left a real 7760 streaming — the selector byte differs by model, and the result was discarded so a quiet failure looked like a cure. Both forms go out now (a NAK costs one frame) and the outcomes are logged. The power table also gains its third measured anchor: a real 200 W reads full deflection, so raw 213 is 200 W — not the printed face's 250. --- frontend/src/components/IcomPanel.tsx | 6 ++++-- internal/cat/icomserial.go | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/IcomPanel.tsx b/frontend/src/components/IcomPanel.tsx index cb6f59c..d824616 100644 --- a/frontend/src/components/IcomPanel.tsx +++ b/frontend/src/components/IcomPanel.tsx @@ -141,11 +141,13 @@ function fmtVFO(hz?: number): string { // with raw 213 = full scale = 250 W. The face is not linear in watts at the // bottom — a two-segment guess showed 50 W as 62 — so watts interpolate // between the measured anchors, and a new measurement just adds a row. -const ICOM_7760_PO: [number, number][] = [[0, 0], [89, 50], [143, 100], [213, 250]]; +// Third measured anchor (2026-08-30): a real 200 W read full deflection — +// raw 213 is 200 W on this rig, not the 250 the printed face suggests. +const ICOM_7760_PO: [number, number][] = [[0, 0], [89, 50], [143, 100], [213, 200]]; function icomWatts(pct: number): { w: number; defl: number } { const raw = Math.max(0, pct * 2.55); const defl = raw <= 143 ? (raw / 143) * 50 : Math.min(100, 50 + ((raw - 143) / 70) * 50); - let w = 250; + let w = 200; for (let i = 1; i < ICOM_7760_PO.length; i++) { const [r0, w0] = ICOM_7760_PO[i - 1], [r1, w1] = ICOM_7760_PO[i]; if (raw <= r1) { w = w0 + ((raw - r0) / (r1 - r0)) * (w1 - w0); break; } diff --git a/internal/cat/icomserial.go b/internal/cat/icomserial.go index aa6918f..b08f71d 100644 --- a/internal/cat/icomserial.go +++ b/internal/cat/icomserial.go @@ -277,8 +277,12 @@ func (b *IcomSerial) Connect() error { // acknowledgement. The front-panel display is deliberately untouched. // Synchronously: Connect already runs on the CAT goroutine, and a stray // goroutine writing to the shared link would interleave with the command - // loop. One 350 ms wait at most, once per connect. - _ = b.execScope("waveform output off (leftover)", civ.SubScopeOn, 0) + // loop. Two forms, because the selector byte differs by model and a NAK + // costs one frame — and the results are LOGGED, because a kill that quietly + // fails leaves the flood running and the next dropout unexplained. + err1 := b.execScope("waveform output off (leftover)", civ.SubScopeOn, 0) + err2 := b.exec(civ.CmdScope, civ.SubScopeOn, 0x00, 0x00) // main-selector form + applog.Printf("icom: waveform-off sent at connect (plain: %v, with selector: %v)", err1, err2) // Defer the DSP snapshot until the rig actually answers CI-V. Over the network // the rig may still be booting (or off) at Connect, so an immediate readDSP // would time out and leave every control at 0 / off with no retry. ReadState