feat: the Yaesu console follows the mode — CW gets its own controls
Microphone gain and VOX are meaningless in CW: the rig ignores both, so showing them is showing dead controls. They are hidden, and a CW card takes their place with keyer speed (KS), break-in (BI) and ZIN (ZI), the zero-in that retunes so the station being received lands on the operator's own pitch. ZIN is a one-shot with no state, so it is a plain button rather than a chip that would look latched, and no settings read-back follows — the frequency change arrives through the normal poll like any other. The keyer values are read on the slow beat whatever the mode, so the card is already populated the instant the operator switches to CW instead of filling in a poll cycle later. Which controls show is decided by the RIG's mode, not the logged one: the logged mode can be a digital sub-mode the radio knows nothing about.
This commit is contained in:
@@ -5,7 +5,7 @@ import {
|
||||
SetYaesuPower, SetYaesuMicGain, SetYaesuAFGain, SetYaesuRFGain, SetYaesuSquelch,
|
||||
SetYaesuAGC, SetYaesuPreamp, SetYaesuAtt, SetYaesuNB, SetYaesuNR, SetYaesuNRLevel,
|
||||
SetYaesuNarrow, SetYaesuVOX, SetYaesuSplit, SetYaesuBand, TuneYaesuATU,
|
||||
SetYaesuModeRaw, SetYaesuSplitOffset, GetCATState,
|
||||
SetYaesuModeRaw, SetYaesuSplitOffset, SetYaesuKeySpeed, SetYaesuBreakIn, YaesuZeroIn, GetCATState,
|
||||
} from '../../wailsjs/go/main/App';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
@@ -19,7 +19,7 @@ type YaesuState = {
|
||||
rf_power: number; mic_gain: number; af_gain: number; rf_gain: number; squelch: number;
|
||||
agc?: string; preamp: number; att: number;
|
||||
nb: boolean; nr: boolean; nr_level: number; narrow: boolean; vox: boolean;
|
||||
split_tx_hz?: number;
|
||||
split_tx_hz?: number; key_speed?: number; break_in?: boolean;
|
||||
};
|
||||
|
||||
const ZERO: YaesuState = {
|
||||
@@ -268,6 +268,9 @@ export function YaesuPanel({ onReportRST }: { onReportRST?: (rst: string) => voi
|
||||
}
|
||||
|
||||
const band = bandOfHz(freqHz);
|
||||
// CW changes what belongs on the panel: no microphone, no VOX, but a keyer
|
||||
// speed, break-in and ZIN. Driven by the RIG's mode, not the logged one.
|
||||
const isCW = (view.raw_mode || '').toUpperCase().startsWith('CW');
|
||||
|
||||
if (!st.available) {
|
||||
return (
|
||||
@@ -427,18 +430,49 @@ export function YaesuPanel({ onReportRST }: { onReportRST?: (rst: string) => voi
|
||||
onChange={(v) => push('rf_power', v, () => SetYaesuPower(v))} />
|
||||
<span className="w-10 text-right text-xs font-mono tabular-nums text-muted-foreground">{view.rf_power}W</span>
|
||||
</Row>
|
||||
<Row label="MIC">
|
||||
<Slider value={view.mic_gain} onChange={(v) => push('mic_gain', v, () => SetYaesuMicGain(v))} />
|
||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{view.mic_gain}</span>
|
||||
</Row>
|
||||
<Row label="VOX">
|
||||
<Chip on={view.vox} onClick={() => push('vox', !view.vox, () => SetYaesuVOX(!view.vox))} label="VOX" />
|
||||
{/* Microphone gain and VOX are meaningless in CW — the rig ignores both
|
||||
— so they are hidden rather than shown as dead controls. */}
|
||||
{!isCW && (
|
||||
<>
|
||||
<Row label="MIC">
|
||||
<Slider value={view.mic_gain} onChange={(v) => push('mic_gain', v, () => SetYaesuMicGain(v))} />
|
||||
<span className="w-8 text-right text-xs font-mono tabular-nums text-muted-foreground">{view.mic_gain}</span>
|
||||
</Row>
|
||||
<Row label="VOX">
|
||||
<Chip on={view.vox} onClick={() => push('vox', !view.vox, () => SetYaesuVOX(!view.vox))} label="VOX" />
|
||||
</Row>
|
||||
</>
|
||||
)}
|
||||
<Row label="">
|
||||
<button type="button" onClick={() => RefreshYaesuPanel().catch((e) => setErr(String(e?.message ?? e)))}
|
||||
className="ml-auto px-2 py-1 rounded-md text-[11px] font-bold border border-border bg-card text-muted-foreground hover:bg-muted">
|
||||
{t('yaesu.refresh')}
|
||||
</button>
|
||||
</Row>
|
||||
</Card>
|
||||
|
||||
{/* CW — only in CW, where these replace the phone controls above. */}
|
||||
{isCW && (
|
||||
<Card icon={Radio} title={t('yaesu.cw')}>
|
||||
<Row label="SPEED">
|
||||
<Slider value={view.key_speed || 20} min={4} max={60} accent="var(--primary)"
|
||||
onChange={(v) => push('key_speed', v, () => SetYaesuKeySpeed(v))} />
|
||||
<span className="w-12 text-right text-xs font-mono tabular-nums text-muted-foreground">{view.key_speed || 20} wpm</span>
|
||||
</Row>
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<Chip on={!!view.break_in} onClick={() => push('break_in', !view.break_in, () => SetYaesuBreakIn(!view.break_in))}
|
||||
label="BK-IN" title={t('yaesu.breakInHint')} />
|
||||
{/* ZIN is a one-shot: the rig retunes so the station being received
|
||||
lands on the operator's own CW pitch. Not a toggle, so it is a
|
||||
plain button rather than a chip that would look latched. */}
|
||||
<button type="button" onClick={() => YaesuZeroIn().catch((e) => setErr(String(e?.message ?? e)))}
|
||||
title={t('yaesu.zinHint')}
|
||||
className="px-2 py-1 rounded-md text-[11px] font-bold border border-border bg-card text-muted-foreground hover:bg-muted">
|
||||
ZIN
|
||||
</button>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user