Skip to content

[tci] Fix TCI TX timing for WSJT-X#1624

Merged
ten9876 merged 1 commit into
aethersdr:mainfrom
jensenpat:aether/tci-wsjtx-tx-timing
Apr 18, 2026
Merged

[tci] Fix TCI TX timing for WSJT-X#1624
ten9876 merged 1 commit into
aethersdr:mainfrom
jensenpat:aether/tci-wsjtx-tx-timing

Conversation

@jensenpat

@jensenpat jensenpat commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator
TCI-QSO-2

Summary

This PR hardens the TCI TX path used by WSJT-X/JTDX and fixes the timing bug that made the radio transmit but produce unreliable or undecodable digital-mode audio.

The changes are concentrated in TciServer so the fix stays cross-platform and applies consistently on macOS, Linux, and Windows.

What Changed

  • treat trx:<rx>,true,tci as a TCI-audio TX request instead of a radio-direct keying request
  • detect WSJT-X's duplicated stereo TX payload layout before resampling
  • replace the fixed 21 ms TX_CHRONO timer with a monotonic elapsed-time accumulator that targets the true 21.333 ms block cadence
  • apply the saved DaxTxGain setting to TCI TX audio so TCI follows the same gain staging as the normal DAX TX path
  • add compact TCI TX summary logs with requested/input/output frame counts, effective sample rate, RMS/peak, clip count, and payload layout hints

Root Cause

WSJT-X only sends TCI TX audio after it receives TX_CHRONO frames from the radio-side server. Each TX_CHRONO request asks for 2048 float samples, which WSJT-X treats as 1024 stereo frames at 48 kHz.

That means each requested block represents 1024 / 48000 = 21.333 ms of audio.

AetherSDR was driving TX_CHRONO with a fixed 21 ms QTimer, which requests audio about 1.6% too fast. In practice, that compresses the transmitted digital audio in time, shifts tones upward, and pushes symbol timing away from what FT8/JT decoders expect. The visible result is a transmitter that keys and makes RF, but produces poor or no decode reliability.

There were two related issues around that main bug:

  • trx:<rx>,true,tci was not routed through the TCI audio path, which could key the radio without ever starting TX_CHRONO
  • WSJT-X writes duplicated L=R float pairs in the TX buffer, and treating those as true mono before resampling can distort block duration and waveform shape

Those are fixed here as well, but the cadence bug is the strongest match for the observed symptom of clean-looking RF that was not decodable until the timing was corrected.

User Impact

After this change, TCI TX behaves much more like a stable digital-mode transport:

  • WSJT-X can key and modulate through TCI reliably
  • FT8/JT audio stays aligned to the expected 48 kHz timing model
  • TX gain is easier to reason about because TCI follows the saved DAX TX gain setting
  • debugging future TCI TX issues is easier because the server now emits concise timing and level summaries

Validation

  • built successfully with cmake --build build --parallel 10
  • confirmed over-the-air PSK Reporter decodes from TCI TX
  • completed two full FT8 QSOs with no retries
  • observed healthy TX metering with the TX meter staying around 0, consistent with clean drive and no obvious splatter

👨🏼‍💻 Generated with OpenAI Codex (GPT-5.4 Pro) and tested by @jensenpat

@jensenpat jensenpat changed the title Fix TCI TX timing for WSJT-X [tci] Fix TCI TX timing for WSJT-X Apr 18, 2026
@jensenpat jensenpat marked this pull request as ready for review April 18, 2026 21:34
@jensenpat jensenpat requested a review from ten9876 as a code owner April 18, 2026 21:34
@ten9876 ten9876 merged commit d33fab9 into aethersdr:main Apr 18, 2026
5 checks passed
@ten9876

ten9876 commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator

Claude here — merged. Solid work, and the OTA FT8 QSO validation is exactly the evidence that would have been hard to simulate synthetically. The 2048/48000 = 21.333 ms math is an unambiguous root cause for the tone-shift that was breaking digital-mode decode.

Thanks @jensenpat — another clean community contribution.

73, Jeremy KK7GWY & Claude (AI dev partner)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants