feat(rigctld): split that actually reaches the radio, or an honest refusal
set_split_vfo and set_split_freq both answered RPRT 0 and did nothing. WSJT-X and JTDX in "Split Operating: Rig" send exactly that pair, believed both, and transmitted on the RECEIVE frequency — on a pileup, straight onto the DX, while showing the operator precisely what they had asked for. A lie that leaves no trace in any log is the worst kind of bug this program can have. The two commands are honoured as a PAIR. Arming alone does nothing on the radio, because WSJT-X sends the frequency second and split armed on whatever the transmit VFO happened to hold is worse than no split at all: it transmits somewhere the operator never chose. The request is remembered and set_split_freq does the work. Kenwood gains SetSplit — FB to place the dial, then FR0/FT1 to arm, in that order for the same reason. It writes what State() already knows how to read. Everything else REFUSES, and that is the feature, not a shortfall. Only Flex and Icom could even toggle split before, neither could set the transmit frequency, and Yaesu, TCI and OmniRig have nothing at all. A refusal WSJT-X can report — and act on, by falling back to Fake It — is worth far more than a success it has no way to check. Both paths are pinned: split reaching the rig as one armed call with the right frequency, and a backend that cannot do it producing an error rather than RPRT 0.
This commit is contained in:
@@ -2,6 +2,7 @@ package rigctld
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
@@ -21,11 +22,26 @@ type fakeRig struct {
|
||||
setFreqs []int64
|
||||
setModes []string
|
||||
failSet bool
|
||||
// noSplit models a backend that cannot set split — the case that must reach
|
||||
// the client as a refusal instead of a silent success.
|
||||
noSplit bool
|
||||
splitCalls []string
|
||||
}
|
||||
|
||||
func (f *fakeRig) Freq() int64 { f.mu.Lock(); defer f.mu.Unlock(); return f.freq }
|
||||
func (f *fakeRig) Mode() string { f.mu.Lock(); defer f.mu.Unlock(); return f.mode }
|
||||
func (f *fakeRig) Split() (bool, int64) { f.mu.Lock(); defer f.mu.Unlock(); return f.split, f.txFreq }
|
||||
|
||||
func (f *fakeRig) SetSplit(on bool, txHz int64) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
if f.noSplit {
|
||||
return errors.New("this radio cannot set split from software")
|
||||
}
|
||||
f.splitCalls = append(f.splitCalls, fmt.Sprintf("%v:%d", on, txHz))
|
||||
f.split, f.txFreq = on, txHz
|
||||
return nil
|
||||
}
|
||||
func (f *fakeRig) SetFreq(hz int64) error {
|
||||
f.mu.Lock()
|
||||
defer f.mu.Unlock()
|
||||
|
||||
Reference in New Issue
Block a user