Summary
When the TX slice is not the slice the TCI server is controlling (the arrangement the
#4014 ruling endorses: Pan A = KiwiSDR RX/decode, Pan B = local RF with the TX slice),
WSJT-X's split handling and the TCI server's split reporting contradict each other. The
result is recurring "Rig Control Error" dialogs and TCP drops in WSJT-X; worse, after a
drop the server can keep streaming DAX RX audio to the stale session while the
reconnected client never gets audio re-armed — decodes silently stop until WSJT-X is
restarted.
Environment
Reproduction / evidence
WSJT-X configured with Split Operation = None (Fake It behaves the same; both insist on
rig split off). Log capture of the fight (timestamps 18:08, aether.cat):
18:08:19.876 TCI rx: "audio_stop:0;"
18:08:20.066 TCI rx: "split_enable:false;"
18:08:20.066 TCI tx→client: split_enable:0,true; <-- server contradicts the request
18:08:20.066 TCI rx: "split_enable:0,false;"
18:08:20.066 TciServer: client disconnected (TCP drop), 0 remaining
WSJT-X shows "Rig Control Error", hangs up, reconnects; this repeats intermittently
(whenever WSJT-X re-asserts split state — TX start/stop, periodic checks).
The server's answer is understandable: with the TX slice on a different slice than the
one TCI controls, the radio genuinely is in a split-like state, and honoring
split_enable:false would mean moving TX onto the Kiwi slice — which the panadapter
TX inhibit correctly refuses. But the client can't tell "split refused for a good
reason" from "rig misbehaving".
Split=Rig is not a workaround: WSJT-X then actively manages a TX offset, and the server
applies it to the controlled slice — the KiwiSDR ear moved +500 Hz while TX stayed put
(observed live), i.e. exactly the slice that must stay fixed.
Stranded-audio consequence
After several drop/reconnect rounds, the server continued logging
TCI: DAX RX audio dax_ch=1 slice=0 ... enabled_clients=1 sent_clients=1 every ~2 s
while the live WSJT-X showed a dead dB meter and no decodes — the enabled/sent client
appears to have been the stale session. Kiwi ingestion, injection, and the stall
watchdog were all verified healthy at the same moment (bridge audioCapture showed
kiwi-tagged audio at RMS 0.40). Restarting WSJT-X restored decodes instantly.
Suggested directions (maintainer's call)
- Report split state relative to the TCI-controlled slice (client-facing split = "my
dial vs my TX freq"), or accept split_enable:false without contradiction when the
split-like state is an internal arrangement the client didn't create.
- Independently: on client disconnect, ensure the audio-enabled flag dies with the
session (or re-arm on the next audio_start regardless of stale bookkeeping), so a
drop can't strand the DAX RX stream.
(2) may deserve its own issue — happy to split it if preferred.
Context
Follows the two-pan workflow endorsed in the #4014 ruling; related to #4025/#4026 (Kiwi
RX→DAX decode path) only in that this is the workflow they're used in — the TCI behavior
above is reproducible on main without those changes whenever TX lives on a slice the TCI
client isn't controlling.
Summary
When the TX slice is not the slice the TCI server is controlling (the arrangement the
#4014 ruling endorses: Pan A = KiwiSDR RX/decode, Pan B = local RF with the TX slice),
WSJT-X's split handling and the TCI server's split reporting contradict each other. The
result is recurring "Rig Control Error" dialogs and TCP drops in WSJT-X; worse, after a
drop the server can keep streaming DAX RX audio to the stale session while the
reconnected client never gets audio re-armed — decodes silently stop until WSJT-X is
restarted.
Environment
fix/kiwi-rx-dax@670d438e(current main + PR feat(kiwi): route KiwiSDR audio to the slice's DAX channel for WSJT-X/digimodes #4026; the TCI code involvedis main's), Linux, FLEX-8400 fw 4.2.18.41174
RF, TX slice, both 7.074 FT8
Reproduction / evidence
WSJT-X configured with Split Operation = None (Fake It behaves the same; both insist on
rig split off). Log capture of the fight (timestamps 18:08,
aether.cat):WSJT-X shows "Rig Control Error", hangs up, reconnects; this repeats intermittently
(whenever WSJT-X re-asserts split state — TX start/stop, periodic checks).
The server's answer is understandable: with the TX slice on a different slice than the
one TCI controls, the radio genuinely is in a split-like state, and honoring
split_enable:falsewould mean moving TX onto the Kiwi slice — which the panadapterTX inhibit correctly refuses. But the client can't tell "split refused for a good
reason" from "rig misbehaving".
Split=Rig is not a workaround: WSJT-X then actively manages a TX offset, and the server
applies it to the controlled slice — the KiwiSDR ear moved +500 Hz while TX stayed put
(observed live), i.e. exactly the slice that must stay fixed.
Stranded-audio consequence
After several drop/reconnect rounds, the server continued logging
TCI: DAX RX audio dax_ch=1 slice=0 ... enabled_clients=1 sent_clients=1every ~2 swhile the live WSJT-X showed a dead dB meter and no decodes — the enabled/sent client
appears to have been the stale session. Kiwi ingestion, injection, and the stall
watchdog were all verified healthy at the same moment (bridge
audioCaptureshowedkiwi-tagged audio at RMS 0.40). Restarting WSJT-X restored decodes instantly.
Suggested directions (maintainer's call)
dial vs my TX freq"), or accept
split_enable:falsewithout contradiction when thesplit-like state is an internal arrangement the client didn't create.
session (or re-arm on the next
audio_startregardless of stale bookkeeping), so adrop can't strand the DAX RX stream.
(2) may deserve its own issue — happy to split it if preferred.
Context
Follows the two-pan workflow endorsed in the #4014 ruling; related to #4025/#4026 (Kiwi
RX→DAX decode path) only in that this is the workflow they're used in — the TCI behavior
above is reproducible on main without those changes whenever TX lives on a slice the TCI
client isn't controlling.