feat: multiple amplifiers + SmartSDR v4 DSP filters

Multi-amp: Settings->Amplifier becomes a list (amps.json, legacy single-amp keys auto-migrate to entry #1); one client per enabled amp with per-id bindings (GetAmplifiers/SaveAmplifiers/GetAmpStatuses/AmpOperate/AmpPower/AmpPowerLevel/AmpFanMode); legacy a.pgxl/a.spe/a.acom point at the first enabled amp of each family. Amp cards in FlexPanel and Station Control gain a dropdown to pick the amp; the status bar shows one clickable chip per amp. Use case: two SPEs run in parallel.

Flex v4 DSP (8000/Aurora): NRL/ANFL (lms_nr/lms_anf), NRS (speex_nr), NRF (nrf) with level sliders, RNN (rnnoise) and ANFT on/off — keys per the FlexLib slice docs; the section only shows when the radio reports these keys (dsp_v4 flag), so 6000-series panels are unchanged.
This commit is contained in:
2026-07-22 17:25:10 +02:00
parent 4c75680689
commit b7dd8d4852
12 changed files with 1051 additions and 411 deletions
+75 -50
View File
@@ -259,30 +259,30 @@ type FlexSliceInfo struct {
}
type FlexTXState struct {
Available bool `json:"available"` // backend is Flex and handshaked
Model string `json:"model,omitempty"`
Available bool `json:"available"` // backend is Flex and handshaked
Model string `json:"model,omitempty"`
// Slices lists every in-use receiver slice (A/B/C/D…) so the panel can show
// them all and highlight the active one. The active slice drives everything.
Slices []FlexSliceInfo `json:"slices,omitempty"`
RFPower int `json:"rf_power"`
TunePower int `json:"tune_power"`
Tune bool `json:"tune"` // tune carrier active
Transmitting bool `json:"transmitting"` // interlock state = TRANSMITTING
VoxEnable bool `json:"vox_enable"`
VoxLevel int `json:"vox_level"`
VoxDelay int `json:"vox_delay"`
ProcEnable bool `json:"proc_enable"`
ProcLevel int `json:"proc_level"`
Mon bool `json:"mon"`
MonLevel int `json:"mon_level"`
MicLevel int `json:"mic_level"`
TXFilterLow int `json:"tx_filter_low"` // TX filter low cut (Hz)
TXFilterHigh int `json:"tx_filter_high"` // TX filter high cut (Hz)
Slices []FlexSliceInfo `json:"slices,omitempty"`
RFPower int `json:"rf_power"`
TunePower int `json:"tune_power"`
Tune bool `json:"tune"` // tune carrier active
Transmitting bool `json:"transmitting"` // interlock state = TRANSMITTING
VoxEnable bool `json:"vox_enable"`
VoxLevel int `json:"vox_level"`
VoxDelay int `json:"vox_delay"`
ProcEnable bool `json:"proc_enable"`
ProcLevel int `json:"proc_level"`
Mon bool `json:"mon"`
MonLevel int `json:"mon_level"`
MicLevel int `json:"mic_level"`
TXFilterLow int `json:"tx_filter_low"` // TX filter low cut (Hz)
TXFilterHigh int `json:"tx_filter_high"` // TX filter high cut (Hz)
// Mic profiles (SmartSDR): the list of available profiles + the loaded one.
MicProfile string `json:"mic_profile,omitempty"`
MicProfiles []string `json:"mic_profiles,omitempty"`
ATUStatus string `json:"atu_status,omitempty"`
ATUMemories bool `json:"atu_memories"`
MicProfile string `json:"mic_profile,omitempty"`
MicProfiles []string `json:"mic_profiles,omitempty"`
ATUStatus string `json:"atu_status,omitempty"`
ATUMemories bool `json:"atu_memories"`
// Active RX slice DSP controls.
RXAvail bool `json:"rx_avail"` // an RX slice exists
Split bool `json:"split"` // RX/TX on separate slices
@@ -304,6 +304,20 @@ type FlexTXState struct {
ANFLevel int `json:"anf_level"`
WNB bool `json:"wnb"`
WNBLevel int `json:"wnb_level"`
// SmartSDR v4 DSP (8000/Aurora series): NRL/ANFL (legacy LMS), NRS
// (spectral subtraction), RNN (AI NR), ANFT (FFT notch), NRF (NR w/filter).
// DSPV4 is true once the radio reported any of these keys — gates the UI.
LMSNR bool `json:"lms_nr"`
LMSNRLevel int `json:"lms_nr_level"`
LMSANF bool `json:"lms_anf"`
LMSANFLevel int `json:"lms_anf_level"`
SpeexNR bool `json:"speex_nr"`
SpeexNRLevel int `json:"speex_nr_level"`
RNN bool `json:"rnn"`
ANFT bool `json:"anft"`
NRF bool `json:"nrf"`
NRFLevel int `json:"nrf_level"`
DSPV4 bool `json:"dsp_v4"`
// RIT/XIT — offsets applied to the active slice's RX / TX frequency without
// moving the slice. The offset survives the switch being turned off, so
// re-enabling restores it, exactly like the radio's own knob.
@@ -337,7 +351,7 @@ type FlexMeter struct {
Src string `json:"src,omitempty"` // SLC / TX- / RAD / AMP…
Name string `json:"name,omitempty"` // FWDPWR, SWR, LEVEL, PATEMP…
Unit string `json:"unit,omitempty"`
Slice int `json:"slice"` // for SLC meters, the slice index it belongs to; -1 otherwise
Slice int `json:"slice"` // for SLC meters, the slice index it belongs to; -1 otherwise
Value float64 `json:"value"`
Lo float64 `json:"lo"`
Hi float64 `json:"hi"`
@@ -386,6 +400,17 @@ type FlexController interface {
SetAPFLevel(int) error
SetWNB(bool) error
SetWNBLevel(int) error
// SmartSDR v4 DSP (8000/Aurora): NRL / ANFL / NRS / RNN / ANFT / NRF.
SetLMSNR(bool) error
SetLMSNRLevel(int) error
SetLMSANF(bool) error
SetLMSANFLevel(int) error
SetSpeexNR(bool) error
SetSpeexNRLevel(int) error
SetRNN(bool) error
SetANFT(bool) error
SetNRF(bool) error
SetNRFLevel(int) error
SetRIT(bool) error
SetRITFreq(int) error
SetXIT(bool) error
@@ -445,7 +470,7 @@ type IcomTXState struct {
// Transmit + live status (polled).
Transmitting bool `json:"transmitting"`
Split bool `json:"split"`
SMeter int `json:"s_meter"` // 0-100 (raw 0-255; S9≈120)
SMeter int `json:"s_meter"` // 0-100 (raw 0-255; S9≈120)
PowerMeter int `json:"power_meter"` // 0-100 (TX Po)
SWRMeter int `json:"swr_meter"` // 0-100 (TX SWR)
// RIT / ΔTX (XIT).
@@ -456,20 +481,20 @@ type IcomTXState struct {
KeySpeedWPM int `json:"key_speed_wpm"` // current KEY SPEED in WPM
BreakIn int `json:"break_in"` // CW break-in: 0=OFF, 1=SEMI, 2=FULL
// Set controls.
RFPower int `json:"rf_power"` // 0-100 (TX output)
MicGain int `json:"mic_gain"` // 0-100
AFGain int `json:"af_gain"`
RFGain int `json:"rf_gain"`
NB bool `json:"nb"`
NBLevel int `json:"nb_level"`
NR bool `json:"nr"`
NRLevel int `json:"nr_level"`
ANF bool `json:"anf"`
APF bool `json:"apf"` // audio peak filter (CW only)
AGC string `json:"agc,omitempty"` // FAST | MID | SLOW
Preamp int `json:"preamp"` // 0=off, 1=P.AMP1, 2=P.AMP2
Att int `json:"att"` // dB attenuation, 0=off
Filter int `json:"filter"` // 1 | 2 | 3 (FIL1/2/3)
RFPower int `json:"rf_power"` // 0-100 (TX output)
MicGain int `json:"mic_gain"` // 0-100
AFGain int `json:"af_gain"`
RFGain int `json:"rf_gain"`
NB bool `json:"nb"`
NBLevel int `json:"nb_level"`
NR bool `json:"nr"`
NRLevel int `json:"nr_level"`
ANF bool `json:"anf"`
APF bool `json:"apf"` // audio peak filter (CW only)
AGC string `json:"agc,omitempty"` // FAST | MID | SLOW
Preamp int `json:"preamp"` // 0=off, 1=P.AMP1, 2=P.AMP2
Att int `json:"att"` // dB attenuation, 0=off
Filter int `json:"filter"` // 1 | 2 | 3 (FIL1/2/3)
// Antenna (IC-7610 = ANT1/ANT2).
Antenna int `json:"antenna"` // 1 | 2 (0 = unknown)
// Filter fine controls: Twin PBT + manual notch (0-100, 50 = centre).
@@ -510,20 +535,20 @@ type IcomController interface {
SetMicGain(int) error
SetIcomSplit(bool) error
TuneATU() error
SetScope(bool) error // enable/disable the spectrum-scope waveform stream
SetScopeMode(bool) error // true = fixed span, false = center-on-VFO
SetScope(bool) error // enable/disable the spectrum-scope waveform stream
SetScopeMode(bool) error // true = fixed span, false = center-on-VFO
SetScopeEdges(int64, int64) error // point the fixed scope at low..high Hz (centre/pan)
ScopeData() ScopeSweep // latest assembled sweep (empty until enabled)
SetRIT(int) error // RIT/ΔTX offset in signed Hz
SetRITOn(bool) error // RIT on/off
SetXITOn(bool) error // ΔTX (XIT) on/off
SendCW(string) error // key a CW message via the rig's keyer (CI-V 0x17)
StopCW() error // abort the CW message being sent
SetKeySpeed(int) error // CW keyer speed in WPM
SetBreakIn(int) error // CW break-in: 0=OFF, 1=SEMI, 2=FULL
SetAntenna(int) error // 1 = ANT1, 2 = ANT2
SetPBTInner(int) error // Twin PBT inside (0-100, 50 = centre)
SetPBTOuter(int) error // Twin PBT outside (0-100, 50 = centre)
ScopeData() ScopeSweep // latest assembled sweep (empty until enabled)
SetRIT(int) error // RIT/ΔTX offset in signed Hz
SetRITOn(bool) error // RIT on/off
SetXITOn(bool) error // ΔTX (XIT) on/off
SendCW(string) error // key a CW message via the rig's keyer (CI-V 0x17)
StopCW() error // abort the CW message being sent
SetKeySpeed(int) error // CW keyer speed in WPM
SetBreakIn(int) error // CW break-in: 0=OFF, 1=SEMI, 2=FULL
SetAntenna(int) error // 1 = ANT1, 2 = ANT2
SetPBTInner(int) error // Twin PBT inside (0-100, 50 = centre)
SetPBTOuter(int) error // Twin PBT outside (0-100, 50 = centre)
SetManualNotch(bool) error
SetNotchPos(int) error // manual-notch position (0-100, 50 = centre)
SetSquelch(int) error