From 8cc6997eec1333c5ecfa7624e393061071efb3a4 Mon Sep 17 00:00:00 2001 From: rouggy Date: Wed, 29 Jul 2026 11:59:58 +0200 Subject: [PATCH] =?UTF-8?q?feat:=20colour=20the=20Yaesu=20S-meter=20like?= =?UTF-8?q?=20a=20real=20one=20=E2=80=94=20green,=20amber=20past=20S9,=20r?= =?UTF-8?q?ed=20at=20+20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bar was one colour for its whole travel, so nothing distinguished a signal that is merely readable from one that belongs in the log as 59+20. Green to S9, amber through the S9+ range, red from +20 dB. The thresholds are computed from the SAME S9 point the label uses rather than hard-coded percentages: the S9 position is still a hypothesis on this rig, and when it is corrected the colours have to move with it or the meter would say 59+20 in amber. --- frontend/src/components/YaesuPanel.tsx | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/YaesuPanel.tsx b/frontend/src/components/YaesuPanel.tsx index 612eadd..800da89 100644 --- a/frontend/src/components/YaesuPanel.tsx +++ b/frontend/src/components/YaesuPanel.tsx @@ -105,15 +105,31 @@ function bandOfHz(hz?: number): string { // falls; the front panel puts it at roughly half travel, which is the 50 used // here. That figure is a HYPOTHESIS — if reports come out consistently one S // unit off on a radio, this is the number to correct, not the RST helper. +const S9_PCT = 50; // where S9 falls on the 0-100 reading (see above) +const DB_PER_PCT = 60 / 50; // above S9 the scale runs to roughly +60 dB + function sParts(v: number): { s: number; over: number; label: string } { - if (v >= 50) { - const over = Math.max(0, Math.round((v - 50) * 60 / 50)); + if (v >= S9_PCT) { + const over = Math.max(0, Math.round((v - S9_PCT) * DB_PER_PCT)); return { s: 9, over, label: over > 0 ? `S9+${over}` : 'S9' }; } - const s = Math.max(0, Math.min(9, Math.round(v / 5.5))); + const s = Math.max(0, Math.min(9, Math.round(v / (S9_PCT / 9)))); return { s, over: 0, label: `S${s}` }; } +// Segment colour, the way a radio's own meter is printed: green up to S9, amber +// through the S9+ range, red once the signal is strong enough to be reported as +// 59+20 or more. Derived from the SAME S9 point as the label, so the colour +// change always lands exactly where the numbers say it should — if the S9 point +// is ever corrected, the colours follow on their own. +const RED_OVER_DB = 20; +function sSegColor(frac: number): string { + const pct = frac * 100; + if (pct < S9_PCT) return '#16a34a'; + if ((pct - S9_PCT) * DB_PER_PCT < RED_OVER_DB) return '#f59e0b'; + return '#dc2626'; +} + function Slider({ value, onChange, disabled, accent = 'var(--primary)', min = 0, max = 100 }: { value: number; onChange: (v: number) => void; disabled?: boolean; accent?: string; min?: number; max?: number; }) { @@ -311,7 +327,7 @@ export function YaesuPanel({ onReportRST }: { onReportRST?: (rst: string) => voi consoles read alike instead of each having its own instrument style. */}
- { const sp = sParts(view.s_meter); onReportRST(sMeterRST(sp.s, sp.over, view.mode)); } : undefined} title={onReportRST ? t('yaesu.sToRst') : undefined} />