An FT8 transmission, second by second

published:

FT8 sounds like a chorus of out-of-tune piccolos having a brief panic attack. Twelve and a bit seconds of warbling, repeating every fifteen, somehow containing an entire contact between two stations on opposite sides of the planet. Dial-up modems at least had the decency to be loud about what they were doing.

Here's what those tones are doing, second by second, from the moment someone clicks "Enable TX" to the moment a near-identical string lights up on a screen 8000 km away.

The whole transmission as a receiver sees it. 12.64 seconds wide, eight 8-FSK tones tall, spaced 6.25 Hz apart. The 79 tones aren't pseudo-random fill, they're the literal output of an FT8 encoder running in your browser on "CQ W5ISP EM13". Drag the cursor or flip auto-play to step through. The amber staircase (3, 1, 4, 0, 6, 5, 2) is the Costas array, repeated three times. Everything else hangs off it.

Before t = 0: the computer does the hard part

The radio's job in FT8 is mostly to stay out of the way. The actual work happens in software, where your message gets compressed into 77 bits and not one bit more. "CQ W5ISP EM13" fits comfortably. A heartfelt paragraph about your antenna does not. The protocol is constitutionally incapable of small talk, which depending on your view of amateur radio is either a tragedy or its single greatest feature.

A source encoder that knows the shape of a QSO does the squeezing: callsigns hash to integer indices, grids pack into 15 bits, signal reports are small offsets from a base, and three bits up front declare which of the message-type schemas applies. From there:

  1. CRC-14 over the 77 bits, appended. 91 bits.
  2. LDPC(174,91) doubles that to 174 bits. The extra 83 are parity, smeared across the codeword so noise has to chew through a lot of it before anything is unrecoverable. This is the part that buys you decodes at -24 dB SNR.
  3. Group the 174 bits three at a time, Gray-code the result, and you have 58 symbols numbered 0 through 7.

Three Costas arrays get spliced in (start, middle, end), the sequence [3, 1, 4, 0, 6, 5, 2] each time. 7 + 29 + 7 + 29 + 7 = 79 symbols, 160 ms each, 12.64 seconds total. The symbol rate and tone spacing are both 6.25, which is not an accident: it makes the eight tones orthogonal at symbol boundaries, which is the cleanest possible situation for the demodulator on the other end.

Same pipeline, drawn so the bit counts tell the story. 77 in, 91 after CRC, 174 after LDPC, 58 octal symbols, 79 on-air after Costas insertion. The miniaturized spectrogram at the bottom is what actually goes out.

t = 0 ms: the carrier appears

The transmission starts exactly 500 ms into a 15-second UTC slot. PA drive ramps from zero over the first few ms of symbol one, because the alternative is splattering keyclicks across the band and earning the eternal contempt of the operator on the next 25 Hz bin over.

t = 0 ms to 1.12 s: first Costas array

Seven symbols of [3, 1, 4, 0, 6, 5, 2], chosen for the property that no time-or-frequency shift of the pattern looks like itself. The receiver, which does not know your transmit frequency to within 6.25 Hz or your start time to within 160 ms, slides this template across the spectrogram in both axes. There is exactly one place where the score spikes, and that place is your signal. Sync done.

t = 1.12 to 5.76 s: first data block

29 symbols carrying 87 bits of LDPC codeword, hopping between the eight tone slots in a pattern that looks random because, post-LDPC, it is. The receiver runs eight matched filters in parallel and keeps soft confidence values for every bit, because giving the decoder hard yes/no decisions throws away 2-3 dB of margin and FT8 has zero dB to spare.

t = 5.76 to 6.88 s: middle Costas array

Same seven symbols again. The receiver uses this for two things: a fresh fix on timing and frequency in case the ionosphere is being twitchy, and a second shot at initial sync if the first Costas got eaten by a noise burst.

t = 6.88 to 11.52 s: second data block

The other 87 bits. Once the second block lands, the receiver has 174 soft-valued bit estimates and starts running belief propagation on the LDPC graph. After 20 to 50 iterations it either converges on a valid codeword or it doesn't. If it does, you have 91 candidate bits.

t = 11.52 to 12.64 s: final Costas array, then silence

Seven sync symbols, PA ramps to zero, transmission ends. By now sync is long since locked, but the third Costas is there for symmetry and so the decoder can still recover the message if either of the other two Costas blocks got obliterated.

t > 12.64 s: the receiver does the rest

CRC check on the 91 bits. If it passes, the source decoder reads the i3 message-type bits, unpacks the matching schema, looks up callsign hashes against its recently-heard table, expands the grid, and "CQ W5ISP EM13" pops up in WSJT-X with a frequency offset and an SNR. If the CRC fails, the decoder's apparent success was a false alarm (the noise happened to look like some other valid codeword), and the result gets dropped on the floor.

WSJT-X does this for every 6.25 Hz bin in a 2500 Hz passband, in parallel, every 15 seconds. On a good 20m evening, one slot can produce 30 or 40 decodes from stations scattered across the planet. The dial-up modem had it easy: 4 kHz of clean phone line and 30 dB SNR. FT8 has 50 Hz of HF and sometimes -24 dB. Same idea, harder problem, weirder noises.