feat: Yaesu control panel (meters, bands, DSP, TX), and drop a stale Flex hint

A console pane for the native Yaesu backend, in the same shape as the Icom and
Flex ones: S/PO/SWR meters, band and mode rows, AF/RF/squelch, AGC, the IPO/AMP1/
AMP2 front-end selector, ATT, NB, DNR + level, narrow filter, power in watts, mic
gain, VOX, split and ATU tune.

Three decisions worth keeping:

Panel reads are STAGGERED and live in their own file, away from ReadState. Meters
poll every cycle; settings only change when someone turns a knob, so they refresh
every 8th cycle and right after any set. Polling all of it every cycle would put
twenty queries a second on the serial link the frequency display shares.

Band buttons use the rig's own band memory (BS) rather than a frequency we pick,
so 20 m lands where the operator last was on 20 m — what the radio's own band
keys do.

A set is followed by a read-back, so the panel shows what the RIG ended up with,
not what we asked for; the two differ whenever a value is out of range or the
mode forbids the control. And a control the model lacks keeps its previous value
instead of dropping to zero, which reads as a setting that reset itself.

The S9 point of the S-meter scale is a hypothesis (the manual does not state it)
and is commented as such — one number to correct if reports come out an S unit
off, rather than a fudge spread through the RST helper.

Also removes the FlexRadio settings blurb, which explained the backend to
someone who had already chosen it.
This commit is contained in:
2026-07-29 11:17:08 +02:00
parent e2aba828a9
commit 842d4708a7
12 changed files with 1072 additions and 15 deletions
+91
View File
@@ -14887,3 +14887,94 @@ func (a *App) reloadCATShare(s CATSettings) {
}
a.catShare = srv
}
// ── Yaesu control panel bindings ──────────────────────────────────────────
//
// One thin binding per control, mirroring the Icom set. Each dispatches onto the
// CAT goroutine, so a click never races the poll loop for the serial port.
func (a *App) GetYaesuState() cat.YaesuTXState {
if a.cat == nil {
return cat.YaesuTXState{}
}
st, _ := a.cat.YaesuState()
return st
}
func (a *App) RefreshYaesuPanel() error {
if a.cat == nil {
return fmt.Errorf("CAT not initialized")
}
return a.cat.YaesuDo(func(y cat.YaesuController) error { return y.RefreshYaesu() })
}
func (a *App) SetYaesuPower(w int) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuPower(w) })
}
func (a *App) SetYaesuMicGain(p int) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuMicGain(p) })
}
func (a *App) SetYaesuAFGain(p int) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuAFGain(p) })
}
func (a *App) SetYaesuRFGain(p int) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuRFGain(p) })
}
func (a *App) SetYaesuSquelch(p int) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuSquelch(p) })
}
func (a *App) SetYaesuAGC(mode string) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuAGC(mode) })
}
func (a *App) SetYaesuPreamp(n int) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuPreamp(n) })
}
func (a *App) SetYaesuAtt(db int) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuAtt(db) })
}
func (a *App) SetYaesuNB(on bool) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuNB(on) })
}
func (a *App) SetYaesuNR(on bool) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuNR(on) })
}
func (a *App) SetYaesuNRLevel(n int) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuNRLevel(n) })
}
func (a *App) SetYaesuNarrow(on bool) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuNarrow(on) })
}
func (a *App) SetYaesuVOX(on bool) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuVOX(on) })
}
func (a *App) SetYaesuSplit(on bool) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuSplit(on) })
}
func (a *App) SetYaesuBand(band string) error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.SetYaesuBand(band) })
}
func (a *App) TuneYaesuATU() error {
return a.yaesuDo(func(y cat.YaesuController) error { return y.TuneYaesuATU() })
}
func (a *App) yaesuDo(fn func(cat.YaesuController) error) error {
if a.cat == nil {
return fmt.Errorf("CAT not initialized")
}
return a.cat.YaesuDo(fn)
}