FT-8 Project?

Simon Brown • September 13, 2026

Project for 2027?

Love it or hate it, FT-8 is here to stay. I use WSJT-X to monitor 2m and sometimes 70cms. As a software developer, it's always rewarding to use one's own software. So I just asked ChatGPT whether it (he, she, they) even knew about FT-8. The response was amazing.


So, this could be the start of a project which is also used for EME and meteor scatter modes. Read on dear reader, read on.

Question (Me)

I've been working with ChatGPT to optimise the digital signal processing (DSP) in my SDR Television software, so ChatGPT and myself have history, ChatGPT knows me well.


I asked ChatGPT "Do you know what FT-8 is? Do you think we could write a better decoder?". That's all I asked.


Reply (ChatGPT)

ChatGPT immediately replied!


Yes — very familiar with FT8, and yes, I think we could build a substantially better decoder, particularly if we approach it as a DSP/SDR problem rather than simply reimplementing WSJT-X.


FT8 is actually a very interesting fit for the sort of work we've been doing with your DVB-S2 decoder.

The current FT8 waveform is:

  • 15-second receive/transmit period
  • 79 symbols
  • 8-FSK
  • 6.25 baud
  • 6.25 Hz tone spacing
  • 50 Hz occupied bandwidth
  • three 7×7 Costas sync blocks
  • 174 transmitted coded bits
  • 77-bit payload + 14-bit CRC
  • LDPC(174,91)
  • Gray-coded 3-bit symbols


The really interesting part is that the LDPC decoder isn't necessarily where the biggest gains are. The front end and candidate generation are extremely important.


I'd build it as a multi-stage decoder, something along these lines:


And then we could add the really powerful stuff:


1. Much better signal detection

Rather than simply looking for obvious FT8 traces in an FFT, I'd exploit the known Costas structure.


The three Costas blocks are known completely, so we effectively have a matched-filter/reference-correlation problem.

That lets us search for:

  • frequency,
  • fractional symbol timing,
  • frequency drift,
  • signal amplitude,
  • phase,
  • possibly time offset

simultaneously.


This is very similar philosophically to what we've been doing with your DVB-S2 SOF/PLHEADER detector.


2. Proper soft 8-FSK metrics

This is where I think we could make a significant improvement.

For every data symbol I'd calculate something like:

E0 E1 E2 E3 E4 E5 E6 E7

and convert those eight tone energies into soft bit LLRs.

Because each tone represents three Gray-coded bits, we can calculate the exact bit likelihood:

  • LLR(bit0)
  • LLR(bit1)
  • LLR(bit2)


rather than making a hard decision on the strongest tone. That gives the LDPC decoder substantially better information.

This is analogous to the lesson we found with your DVB-S2 QPSK decoder: the quality and scaling of the soft information going into LDPC can matter enormously.


3. Better LDPC decoding

FT8's code is LDPC(174,91), with the 91 bits consisting of the 77-bit message plus the CRC.

I'd initially implement:

  • normalized/offset min-sum,
  • sum-product,
  • layered scheduling if applicable,
  • adaptive damping,
  • early termination,
  • CRC-assisted termination.


But I'd also investigate OSD / ordered-statistics decoding as a second-stage decoder. That's particularly interesting for FT8 because the block is tiny. Some modern implementations already experiment with BP, OSD and a-priori-assisted decoding.


4. A-priori decoding

This is probably one of the biggest opportunities.

Suppose we know:

CQ G4ABC IO91


or we're in the middle of a QSO and already know one callsign. We don't have to treat all 77 payload bits as completely unknown. We can inject known information into the LDPC decoder. WSJT-X already uses several AP decoding strategies, including known callsigns and known message structures. But we could make this considerably more systematic.


For example:


5. Multi-signal decoding

This is where I'd really like to push it.

Imagine:


We decode A.

Once A is known, we know exactly what waveform A should have produced.

So:


That can potentially expose signals that were completely buried underneath stronger FT8 transmissions. The original WSJT-X development notes explicitly contemplated signal subtraction and two-pass decoding.


I'd go further and make it iterative:


6. Frequency drift estimation

For HF FT8, a signal isn't necessarily sitting at one perfectly constant frequency.

We could estimate:

f(t) = f0 + f1*t + f2*t²


using the three Costas sequences. Then compensate the entire signal before extracting the data. That should help considerably with marginal signals and drifting oscillators.


And there's a particularly interesting experiment I'd like to do. Rather than immediately trying to beat WSJT-X, I'd build a reference-quality C++17 decoder and compare it against WSJT-X under controlled conditions.


For example:


Generate thousands of known FT8 messages at each SNR, with controlled:

  • frequency offset
  • timing offset
  • frequency drift
  • AWGN
  • fading
  • adjacent signals
  • overlapping signals

and measure actual decode probability.


That would let us identify where the extra dB are coming from, rather than just saying "it decodes better".

FT8 is already capable of roughly −20 dB-class decoding under suitable conditions, with AP decoding providing additional sensitivity. And I think your existing DSP experience would transfer extremely well.


In particular, the things we've learned with your DVB-S2 work:

soft metrics → synchronization → noise estimation → LLR scaling → iterative decoding

are almost exactly the areas I'd concentrate on here.


I would not start by copying the WSJT-X decoder line-for-line.


I'd start with a clean C++17 implementation:

  • Ft8Decoder,
  • Ft8Synchronizer,
  • Ft8Detector,
  • Ft8SoftDemodulator,
  • Ft8Ldpc,
  • Ft8Message


with AVX2 where it actually helps.


Then we can benchmark each stage independently.


If you're interested, I think the first thing to build should be the FT8 soft demodulator + Costas synchronizer, because that will tell us whether there are meaningful gains available before we spend time on the LDPC side.

By Simon Brown August 27, 2026
August 27th, 2026 Default Audio Device When changing the default audio device selection in Windows, SDR Console was following the change but not reapplying the latest volume change. Example: I start playback, adjust the volume, then after a while enable my Bluetooth speaker an go outside. When the speaker is enabled SDR Console switches but didn't apply the change in volume. RDS processing AGC replaced with normalisation, Hilbert filter redesigned. Shouldn't make much difference. MIDI Startup I believe I have found the cause of the slow start of SDR Console. As part of the SDR Console startup I always call midiInGetNumDevs() to get the number of attached MIDI devices, even if the user hasn't enabled MIDI. At some stage in 2026 Microsoft introduced a bug where the first call to midiInGetNumDevs() after starting the computer results in blocking all asynchronous activity if there are no MIDI devices connected. If there are MIDI devices connected then it returns after ~100ms. I now only call midiInGetNumDevs() on startup if there are user definitions. Some programs are experiencing even worse behaviour. There should be a Windows update soon with a fix, but for now the kit below should resolve this problem in 99% of cases. Downloads Download beta kits here .
By Simon Brown August 26, 2026
QO-100 Footprints
By Simon Brown August 26, 2026
SDR Television v1.1.4 User Interface Rearranged ribbon bar, added Forward Error Correction (FEC) to the Home panel. Receiver Currently trying to improve LDPC decoding for low SNR. Part of this work involves reducing CPU load in the LDPC decoder. Planning to add advanced decoding in v1.1.5. Changed the list of FEC / LDPC algorithms, removing min-sum and min-sum correction. Optimised offset min-sum algorithm to reduce CPU load. Optimised Bose-Chaudhuri-Hocquenghem (BCH) processing. Added sum-product. Corrected LLR soft scaling for QPSK. Changed default RRC filter length to 12 symbols, previous value of 30 was too long. Updated Feed-Forward AGC with a design from CoPilot. Optimised Gardner TED RRC filter length, now 25 taps. Increased the receive RRC filter rolloff factor by 25% to capture more energy with weak signals. Reset LDPC after 1 second of inactivity. FEC - LDPC There are now two LDPC algorithms, Offset min-sum, and Sum-product. Sum-product is more sensitive than offset min-sum but currently doesn't work at all for FEC rates lower than 1/2 (1/4, 1/3 and 2/5). When sum-product is selected and the rate is lower than 1/2 then offset min-sum is used. The default damping settings for sum-product are shown below.  The aim is to work on sum-product with the help of ChatGPT in 2027 to get the maximum possible sensitivity. Downloads are at the bottom of this page.
By Simon Brown July 27, 2026
July 26th, 2026 Reuter RSR200B Added initial support. Fobos Finalised support for Fobos SDR, only the Agile firmware is supported. Some early Fobos SDR units had HF2 and HF1 swapped on the case printing. FFT When using NVIDIA CUDA for the FFT the returned buffers now use memory from the heap rather than pinned memory (*). Reduced the CPU load in the FFT Helper DLL. The data from the FFT (CUDA, IPP, OpenCL) is processed to match the display DIPs. When running Broadcast-FM with x4 resolution there were 550 FFT bins per display pixel (DIP). These 550 bins were averaged which takes quite some processing, especially when running a matrix display with many receivers enabled. I now down-sample the bins to a maximum of (about) 32 which doesn't affect the display or any DSP but does reduce the CPU. Frequency Database Loading of the frequency database into memory-mapped backing now much faster. Pluto TX Doppler support for Pluto / LibreSDR. Have tested this by adding debug info, seems OK 🙂 . RDS Added variable font size in the RDS editor window. Forced uppercase of PS text in the RDS Editor removed. Change to RDS Logfile updates while the editor is open & visible. Updates are now allowed, previously not so. Recordings Fixed font size error in the playback, navigation window (was incorrect logic). When starting the video recorder a sanity check makes sure the selected folder exists and is accessible. Satellite Satellite definition file format has changed, no need to update your settings but support for the new OMM (.xml) format is included. I'm hosting satellite data on my (new) Akamai server, these is currently a cache of the Celestrak data. I'll add a web page soon which explains what's been happening. Transmit Audio mute is now a per-profile setting. Other Fixed an error opening the matrix display while the SDR was already started. Crash when selecting "Configure" from the Select Radio window fixed. Does not create an error when the graphics driver restarts.
By Simon Brown July 10, 2026
SDR Television v1.1.3 User Interface Fixed erroneous cursor flicker in Settings help text and Receive, Transmit panes. Fixed error in the spectrum squelch logic. Minor fix/improvement in QPSK LUT lookup for low values. Receiver Use highest possible quality decimation for symbol rates of 333ksps and lower. Added optional Doppler correction for LEO/MEO satellites such as MARMOTsat (July 2026). This will most probably be tweaked when the DVB-S2 transmissions started. Downloads are at the bottom of this page.
By Simon Brown June 12, 2026
SDR Television v1.1.2 June 12th, 2026: Add option to disable audio, thus making more bits available for video, this is for use in DATV contests. Note: 66 ksps sample rate is still experimental, will be improved. Downloads are at the bottom of this page. 
By Simon Brown June 9, 2026
SDR Television v1.1.1 June 9th, 2026: Fixes a fatal bug in the Settings, Camera page. Downloads are at the bottom of this page.
By Simon Brown May 23, 2026
Version 1.6.2 This release fixes two bugs in the new DX Spot feature. The spot age logic incorrectly affected spot display. When the map was zoomed, station markers off the map would be displayed at the top left (0, 0).  Downloads are on the World Map page . Version 1.6.1 This release fixes two fatal bugs in the new DX Spot feature. When the graphics engine is restarted, resources are correctly released. Fixed a resource leak when processing the MoseMove logic. Downloads are on the World Map page . Version 1.6 This release adds the display of DX Spots. Display spots are submitted to PSK Reporter which in turn are relayed by a MQTT Broker running on a high performance Akamia node. Spot Format Each spot consists of these fields: Sequence Frequency Band Mode Signal level Time stamp Sending station call, square, country Receiving station call, square, country Note: The country is the ADIF country. Spots are displayed as they arrive, currently no on-demand database. Bandwidth To reduce bandwidth from the broker, filtering is required for 80m up to and including 15m. Filtering requires at least one field below to be set in a definition: Receiver callsign, square or country. Sender callsign, square or country. Without filtering the bandwith from the broker could be excessive. For LF and VHF+ no filtering is required due to the lower number of spots sent on these bands. In a later version the bandwidth restriction may be reduced.
By Simon Brown May 21, 2026
Version 1.6.1 This release fixes two fatal bugs in the new DX Spot feature. When the graphics engine is restarted, resources are correctly released. Fixed a resource leak when processing the MoseMove logic.  Downloads are on the World Map page . Version 1.6 This release adds the display of DX Spots. Display spots are submitted to PSK Reporter which in turn are relayed by a MQTT Broker running on a high performance Akamia node. Spot Format Each spot consists of these fields: Sequence Frequency Band Mode Signal level Time stamp Sending station call, square, country Receiving station call, square, country Note: The country is the ADIF country. Spots are displayed as they arrive, currently no on-demand database. Bandwidth To reduce bandwidth from the broker, filtering is required for 80m up to and including 15m. Filtering requires at least one field below to be set in a definition: Receiver callsign, square or country. Sender callsign, square or country. Without filtering the bandwith from the broker could be excessive. For LF and VHF+ no filtering is required due to the lower number of spots sent on these bands. In a later version the bandwidth restriction may be reduced.