Skip to content

CW Straight Key netCW UDP keying does not trigger radio TX (firmware 4.1.5) #1973

Description

@ten9876

Symptom

When MIDI straight-key or paddle keying triggers RadioModel::sendCwKey/sendCwPaddle, the radio does not transition to TX (no RF output, no state=TRANSMIT interlock status). This affects all CW keying via netCW UDP — straight key, paddle, and CWX-driven local keyer.

CWX text macros via cwx send work fine (different protocol path), and SmartSDR on Windows keys this same radio without issue, so this is AetherSDR-specific.

Reproduction

  1. Set slice 0 to mode=CW, break_in=1, qsk=1
  2. Connect a MIDI controller mapped to CW Straight Key
  3. Press the MIDI button
  4. Observe: no transmit, no interlock state change

Log evidence

Every TCP fallback of cw key/cw ptt returns 0x50001000 ("command not supported"):

TX: "C72|cw ptt 1 time=0xc5e56538 index=1 client_handle=0x70000d28"
TX: "C73|cw key 1 time=0xc5e56538 index=2 client_handle=0x70000d28"
RX: "R72|50001000|"
RX: "R73|50001000|"

This TCP rejection is expected — those decorated commands are netCW-UDP-only in FlexLib. But the UDP path also produces no observable effect:

  • 4 redundant UDP packets are sent at 0/5/10/15 ms (PanadapterStream::sendToRadio confirms sent=85 sent=85 sent=85 sent=85).
  • Radio interlock state stays at READY throughout — never PTT_REQUESTED, never TRANSMIT.
  • Radio sends no status update of any kind in response.

What we ruled out

Several FlexLib-alignment fixes shipped in PR #1969 made the wire format byte-identical to FlexLib reference, but none changed the symptom:

  1. PTT pairing (Radio.cs:8890-8965): sendCwKey now wraps cw key with cw ptt 1 on press and cw ptt 0 on release.
  2. No payload padding (NetCWStream.cs:107-163): payload is now exact tx_data.Length bytes — 57-byte command produces an 85-byte datagram, not 88.
  3. Per-datagram unique packet_count: each of the 4 redundant UDP datagrams gets its own incrementing VITA-49 packet_count (N, N+1, N+2, N+3) instead of all four sharing N.
  4. Program name: tested both client program AetherSDR (rejected as "unknown client program", error 10000002) and client program SmartSDR-Maestro (also rejected). Neither name unlocks the netCW path, so the 10000002 reply appears informational, not a gate.

VITA-49 packet structure verified against VitaOpusDataPacket.ToBytesTX:

  • Word 0: pkt_type=ExtDataWithStream(3), C=1, T=0, TSI=Other(3), TSF=SampleCount(1), packet_count, packet_size
  • Word 1: stream_id (assigned via stream create netcw)
  • Words 2-3: ClassID OUI=0x001C2D, ICC=0x534C, PCC=0x03E3
  • Words 4-6: zeroed timestamps
  • Then ASCII payload at offset 28

All match FlexLib byte-for-byte.

Hypotheses still open

  1. A subtle byte difference we haven't noticed — best resolved with a pcap diff between SmartSDR and AetherSDR keying the same radio.
  2. A missing pre-flight command the radio expects before honoring netCW from a given client (e.g. some client set or interlock/transmit setup).
  3. netCW handler gated on something other than program name — e.g. client UUID whitelist or a feature flag we don't query.

Next step

Capture pcap (Linux side) while keying:

sudo tcpdump -i any -w /tmp/cw.pcap 'host <radio-ip> and (port 4991 or port 4992)'

Compare in Wireshark against a SmartSDR Windows capture of the same operation.

Workaround

None that meets latency requirements. xmit 1/xmit 0 over TCP works but adds round-trip latency unacceptable for CW keying.

Affected

  • AetherSDR ≥ 0.8.21 on FLEX-8600 firmware 4.1.5 / protocol v1.4.0.0
  • All netCW-UDP paths: straight key, paddle, CWX local keyer

Metadata

Metadata

Assignees

No one assigned

    Labels

    CWCW keying, decode, and operationVITA-49VITA-49 UDP streaming: FFT, waterfall, audio, metersbugSomething isn't workingmaintainer-reviewRequires maintainer review before any action is takenprotocolSmartSDR protocol

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions