diff --git a/frontend/src/components/IcomPanel.tsx b/frontend/src/components/IcomPanel.tsx index 0d6cd1d..84506be 100644 --- a/frontend/src/components/IcomPanel.tsx +++ b/frontend/src/components/IcomPanel.tsx @@ -135,10 +135,20 @@ function fmtVFO(hz?: number): string { // and raw 213 is full scale. On a real 7760 a measured 100 W sits at half // deflection of the 250 W face — the linear ×2.5 first tried showed 140 W for // it. Below half scale watts run 0→100, above it 100→250. +// The anchors are MEASURED on the real radio, not derived: a known 50 W read +// raw ≈89 and a known 100 W read raw 143 (Icom's documented half-deflection), +// 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]]; 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); - const w = raw <= 143 ? (raw / 143) * 100 : Math.min(250, 100 + ((raw - 143) / 70) * 150); + let w = 250; + 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; } + } return { w: Math.round(w), defl }; }