Report preparation
What happened?
After transmitting a CW macro — either via the CWX window or by pressing an Fx function key — the FLEX-6700 does not return to RX when the macro finishes sending. The radio remains stuck in TX state for more than 60 seconds before it eventually recovers on its own. There is no way to force it back to RX promptly from the UI during this window. This regression is reproducible since v0.9.6 and affects all amateur bands.
At the time of the diagnostic snapshot, the active TX slice (Slice 2) is in CW mode on 24.898 MHz (12m) with:
QSK = Yes
break_in = Yes
break_in_delay = 0 ms
sync_cwx = Yes
- CW speed = 27 WPM
The radio correctly transmits the full macro content — the bug is exclusively in the TX teardown path after the last character is sent.
What did you expect?
After the last character of a CW macro is sent, the radio should immediately drop TX and return to RX. With break_in = Yes and break_in_delay = 0 ms, the transition should be instantaneous — this is the radio's normal QSK/break-in behaviour and it works correctly when keying with a hardware paddle. The transmitting flag should return to No and the interlock should clear within a fraction of a second of macro completion.
Steps to reproduce
- Connect to a FLEX-6700 (firmware 4.2.18.41174) via LAN.
- Set a slice to CW mode. Confirm QSK = Yes, Break-In = Yes, Break-In Delay = 0 ms.
- Open the CWX window and enter any macro text (e.g.
CQ CQ DE <CALL> K), OR assign a macro to an Fx key.
- Trigger the macro via the CWX Send button or the Fx key.
- Observe the radio transmitting the macro correctly.
- When the last character finishes sending, observe that the radio does not return to RX.
- Time the delay — the radio remains in TX for more than 60 seconds before self-recovering.
- Repeat on other bands — issue is band-independent.
Regression introduced: v0.9.6
Last known-good version: v0.9.5 (or earlier)
Radio model & firmware
| Field |
Value |
| Model |
FLEX-6700 |
| Firmware |
4.2.18.41174 |
| Protocol |
1.4.0.0 |
OS & version
| Field |
Value |
| OS |
Windows 11 Version 25H2 |
| AetherSDR |
0.9.8 |
| Qt |
6.8.3 (x86_64) |
Diagnostic snapshot (captured 2026-05-07T16:11:18)
Connection and ownership are healthy — this is not a multi-client or network issue.
| Parameter |
Value |
| Connection |
LAN, RTT 5 ms (max 11 ms) |
| TX owned by us |
Yes |
| Multiple clients |
No |
| MOX (current) |
No |
| Transmitting (current) |
No |
| Interlock timeout |
0 (disabled) |
| CW break-in |
Yes |
| CW break-in delay |
0 ms |
| QSK (Slice 2) |
Yes |
| sync_cwx |
Yes |
| CW speed |
27 WPM |
| TX forward power (idle) |
0.00 W |
All TX pipeline meters (TX-/8 *) are at −150 dBFS (floor), confirming the radio is in RX. The snapshot was captured after self-recovery.
Developer Notes
⚠️ Critical protocol constraints (from CLAUDE.md)
"The radio never sends mox= in transmit status messages. Use isTransmitting() (interlock state machine), NOT isMox()."
"cw key immediate not supported — use netcw UDP stream for CW keying."
"Correct break-in command: cw break_in 1 — NOT transmit set break_in=1."
These constraints are central to the root cause analysis below.
Suspected source files and functions
Primary suspects:
-
src/models/CwxModel.cpp / CwxModel.h
The CWX model sends CW macros and must monitor the radio's cwx status for queue-empty events. Check whether the handler for the cwx status update (queue becoming empty or erase=1) correctly triggers TX teardown. If the model issues C<seq>|cwx send 2 "<text>" but never acts on the S<handle>|cwx ... status echo indicating completion, TX is never released.
-
src/models/TransmitModel.cpp / TransmitModel.h
Check whether setMox(false) / the MOX-release path is called after CWX completion. Per the protocol note, isTransmitting() (interlock state) is authoritative — NOT isMox(). If CWX teardown was refactored in v0.9.6 to use isMox() as the guard, that would silently fail since MOX state is never echoed in status messages.
-
src/models/InterlockModel.cpp / InterlockModel.h
The interlock state machine drives isTransmitting(). After CWX macro completion, the client must release the interlock. Verify that applyStatus() correctly parses reason= and tx_client_handle= fields and that the CWX completion path triggers a proper interlock release. A 60-second self-recovery time is consistent with the radio's hardware interlock safety timeout firing when the client holds the interlock indefinitely.
-
src/gui/CwxWindow.cpp (or equivalent applet)
Verify that the CWX window Send button and the Fx key handler share the same code path. If Fx keys dispatch macros via a different slot that bypasses the CWX completion callback registration, that would explain the bug affecting both trigger methods equally since v0.9.6.
-
src/core/RadioCommandQueue.cpp (if present)
Check whether a command batching or debounce change introduced in v0.9.6 delays the mox 0 or interlock-release command past the radio's guard timer.
Logging categories to enable
In Help → Support, enable the following before reproducing:
FlexTCP — raw TCP send/receive (cwx, mox, interlock commands)
CWX — CWX model state and queue events
Transmit — MOX and transmit state transitions
Interlock — interlock acquire/release and reason codes
SliceModel — slice TX state changes
Reproduce the issue, wait for the 60-second self-recovery, then collect the full log.
Expected healthy log sequence:
[FlexTCP] >> C42|cwx send 2 "CQ CQ DE <CALL> K"
[FlexTCP] << R42|00000000|
[FlexTCP] << S<handle>|cwx queue= ← empty queue = macro done on radio
[CWX] queue empty — triggering TX teardown
[FlexTCP] >> C43|mox 0 ← this line MUST appear
[Interlock] reason= (cleared)
[Transmit] isTransmitting() → false
- If
mox 0 never appears after CWX queue empties → TX teardown callback is broken client-side.
- If
mox 0 is sent but the radio does not respond → attach a Wireshark capture of the TCP session.
Potential root causes (ranked by likelihood)
-
Missing mox 0 after CWX queue empty (most likely)
A v0.9.6 change broke or removed the callback that sends mox 0 when the radio signals CWX macro completion (empty queue= field in the cwx status). The radio's own break-in timer does not fire because the client's mox is still asserted. The radio self-recovers via its hardware interlock safety timeout (~60 s).
-
isTransmitting() vs isMox() confusion
The radio never echoes mox= in status messages. If the v0.9.6 refactor introduced a guard like if (isMox()) { sendMox(false); } in the teardown path, it will never evaluate true and the TX release is silently skipped.
-
sync_cwx=Yes missing paired MOX release
The snapshot shows sync_cwx=Yes. If AetherSDR explicitly asserts mox 1 when sync_cwx is active, it must also explicitly send mox 0 on CWX completion. A missing paired release in this code path is a clean fit for the v0.9.6 regression.
-
Interlock not released by client
If InterlockModel is not issuing the correct interlock-release sequence, the radio holds TX until its own guard timer fires. With interlock timeout=0 (disabled in the snapshot), the ~60-second recovery is likely a firmware-internal safety watchdog.
-
CWX / Fx key dispatch path divergence
If both the CWX window and Fx keys exhibit the same symptom, they either share the broken code path or both register the same broken completion callback. Confirm that the Fx key handler calls the same CwxModel::send() entry point as the CWX window button.
aethersdr-slice-troubleshooting-20260507-161124.json
AetherSDR version
0.9.8
Radio model & firmware
Flex 6700 v4.2.18.41174
Operating system
Windows
OS version and hardware
Windows 11 25H2
Report preparation
What happened?
After transmitting a CW macro — either via the CWX window or by pressing an Fx function key — the FLEX-6700 does not return to RX when the macro finishes sending. The radio remains stuck in TX state for more than 60 seconds before it eventually recovers on its own. There is no way to force it back to RX promptly from the UI during this window. This regression is reproducible since v0.9.6 and affects all amateur bands.
At the time of the diagnostic snapshot, the active TX slice (Slice 2) is in CW mode on 24.898 MHz (12m) with:
QSK = Yesbreak_in = Yesbreak_in_delay = 0 mssync_cwx = YesThe radio correctly transmits the full macro content — the bug is exclusively in the TX teardown path after the last character is sent.
What did you expect?
After the last character of a CW macro is sent, the radio should immediately drop TX and return to RX. With
break_in = Yesandbreak_in_delay = 0 ms, the transition should be instantaneous — this is the radio's normal QSK/break-in behaviour and it works correctly when keying with a hardware paddle. Thetransmittingflag should return toNoand the interlock should clear within a fraction of a second of macro completion.Steps to reproduce
CQ CQ DE <CALL> K), OR assign a macro to an Fx key.Regression introduced: v0.9.6
Last known-good version: v0.9.5 (or earlier)
Radio model & firmware
OS & version
Diagnostic snapshot (captured 2026-05-07T16:11:18)
Connection and ownership are healthy — this is not a multi-client or network issue.
All TX pipeline meters (
TX-/8 *) are at −150 dBFS (floor), confirming the radio is in RX. The snapshot was captured after self-recovery.Developer Notes
These constraints are central to the root cause analysis below.
Suspected source files and functions
Primary suspects:
src/models/CwxModel.cpp/CwxModel.hThe CWX model sends CW macros and must monitor the radio's
cwxstatus for queue-empty events. Check whether the handler for thecwxstatus update (queue becoming empty orerase=1) correctly triggers TX teardown. If the model issuesC<seq>|cwx send 2 "<text>"but never acts on theS<handle>|cwx ...status echo indicating completion, TX is never released.src/models/TransmitModel.cpp/TransmitModel.hCheck whether
setMox(false)/ the MOX-release path is called after CWX completion. Per the protocol note,isTransmitting()(interlock state) is authoritative — NOTisMox(). If CWX teardown was refactored in v0.9.6 to useisMox()as the guard, that would silently fail since MOX state is never echoed in status messages.src/models/InterlockModel.cpp/InterlockModel.hThe interlock state machine drives
isTransmitting(). After CWX macro completion, the client must release the interlock. Verify thatapplyStatus()correctly parsesreason=andtx_client_handle=fields and that the CWX completion path triggers a proper interlock release. A 60-second self-recovery time is consistent with the radio's hardware interlock safety timeout firing when the client holds the interlock indefinitely.src/gui/CwxWindow.cpp(or equivalent applet)Verify that the CWX window Send button and the Fx key handler share the same code path. If Fx keys dispatch macros via a different slot that bypasses the CWX completion callback registration, that would explain the bug affecting both trigger methods equally since v0.9.6.
src/core/RadioCommandQueue.cpp(if present)Check whether a command batching or debounce change introduced in v0.9.6 delays the
mox 0or interlock-release command past the radio's guard timer.Logging categories to enable
In Help → Support, enable the following before reproducing:
Reproduce the issue, wait for the 60-second self-recovery, then collect the full log.
Expected healthy log sequence:
mox 0never appears after CWX queue empties → TX teardown callback is broken client-side.mox 0is sent but the radio does not respond → attach a Wireshark capture of the TCP session.Potential root causes (ranked by likelihood)
Missing
mox 0after CWX queue empty (most likely)A v0.9.6 change broke or removed the callback that sends
mox 0when the radio signals CWX macro completion (emptyqueue=field in thecwxstatus). The radio's own break-in timer does not fire because the client'smoxis still asserted. The radio self-recovers via its hardware interlock safety timeout (~60 s).isTransmitting()vsisMox()confusionThe radio never echoes
mox=in status messages. If the v0.9.6 refactor introduced a guard likeif (isMox()) { sendMox(false); }in the teardown path, it will never evaluatetrueand the TX release is silently skipped.sync_cwx=Yesmissing paired MOX releaseThe snapshot shows
sync_cwx=Yes. If AetherSDR explicitly assertsmox 1whensync_cwxis active, it must also explicitly sendmox 0on CWX completion. A missing paired release in this code path is a clean fit for the v0.9.6 regression.Interlock not released by client
If
InterlockModelis not issuing the correct interlock-release sequence, the radio holds TX until its own guard timer fires. Withinterlock timeout=0(disabled in the snapshot), the ~60-second recovery is likely a firmware-internal safety watchdog.CWX / Fx key dispatch path divergence
If both the CWX window and Fx keys exhibit the same symptom, they either share the broken code path or both register the same broken completion callback. Confirm that the Fx key handler calls the same
CwxModel::send()entry point as the CWX window button.aethersdr-slice-troubleshooting-20260507-161124.json
AetherSDR version
0.9.8
Radio model & firmware
Flex 6700 v4.2.18.41174
Operating system
Windows
OS version and hardware
Windows 11 25H2