Skip to main content

FT8 Decoding and Encoding in Python with test/loopback code

Project description

FT8 Decoding and Encoding in Python with test/loopback code

This repository contains Python code to decode and encode FT8, plus a minimal command line interface for reception.

Its primary purpose is as a personal project, but should also be useful if you want to browse the code or use the CLI.

CLI

As of version 0.0.3, PyFT8 can be installed using

pip install PyFT8

and you can use

PyFT8_cli "Keyword1, Keyword2" [-c]

to run the CLI where Keywords specify the input sound device (e.g. "Mic, CODEC") and -c means 'concise' output.

Test scripts

Below are some screenshots from test programs that can be used to look at how the protocols actually work, illustrated with a fairly ordinary waterfall and some zoomed-in depictions of captured signals with an overlay of the syncrhonisation tones that are used to search for the signals (Costas patterns).

waterfall candidate detail

Approach

You won't find many comments in the code; I try to make things as obvious as possible via variable names and logical structure, to minimise the need for comments. Also - this is mainly my plaything, and I find bloated, sprawling code incredibly difficult to read, so I like to keep things very compact so that I can see the bigger picture. If you find an if-then-else spanning several paragraphs, it's probably a mistake.

Do feel free to get in touch and ask how anything works. I might add some diagrams etc at some point too - especially if I find an approach that seems to offer something improved and/or very compact (I'm very pleased for e.g. that the entire candidate search, synch, and demodulate process all works by refering to a single time-frequency grid; read the audio, FFT 5 times for each symbol duration, store it, and that's used for everything that follows.)

Limitations

In pursuit of tight code, I've concentrated on core standard messages, leaving out some of the less-used features. The receive part of the code doesn't (yet) have the full capability of the advanced decoders used in WSJT-x, and so gets only about 50% of the decodes that WSJT-x gets.

Here's my current understanding of the differences:

Step PyFT8 WSJT-X
Find candidate signals Search every possible time/frequency offset for match with the Costas pattern, excluding times where candidates would not complete before the next cycle (i.e. first few seconds of the grid) TBD
Syncronise signals in time See above TBD
Use of FFTs for the above A single time-frequency grid with 5 time samples per symbol and 3 frequency samples per tone Several FFTs per operation, details in VK3JPK's great write-up here
Demodulation Extract 1 sample per symbol, 1 sample per tone grid. Correlate each symbol with Gray code to create Log Likelyhood Ratios for each bit. Noncoherent block detection over 3 symbols - creates LLRs by correlating the 512 possible tone sequences (3 symbols with 8 possible tones each) with the actual received symbols. This is done in the frequency domain by combining the whole-symbol correlations already calculated.
Decoding the FEC code Belief Propagation LDPC decoder Belief Propagation LDPC decoder
Further decoding if LDPC fails None Ordered Statistics Decoding
Further signal extraction None Subtraction of the idealised power of the decoded signals, then rescanning the residual spectrum. Further synchronisation adjustments TBC

Acknowledgements

This project implements a decoder for the FT8 digital mode. FT8 was developed by Joe Taylor, K1JT, Steve Franke, K9AN, and others as part of the WSJT-X project. Protocol details are based on information publicly described by the WSJT-X authors and in related open documentation.

Some constants and tables (e.g. Costas synchronization sequence, LDPC structure, message packing scheme) are derived from the publicly available WSJT-X source code and FT8 protocol descriptions. Original WSJT-X source is © the WSJT Development Group and distributed under the GNU General Public License v3 (GPL-3.0), hence the use of GPL-3.0 in this repository.

Also thanks to Robert Morris for:

  • basicft8(*1) - the first code I properly read when I was wondering whether to start this journey
  • weakmon - much good information

(*1 note: applies to FT8 pre V2)

Other useful resources:

<script data-goatcounter="https://g1ojs-github.goatcounter.com/count" async src="//gc.zgo.at/count.js"></script>

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pyft8-0.1.0.tar.gz (363.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pyft8-0.1.0-py3-none-any.whl (31.9 kB view details)

Uploaded Python 3

File details

Details for the file pyft8-0.1.0.tar.gz.

File metadata

  • Download URL: pyft8-0.1.0.tar.gz
  • Upload date:
  • Size: 363.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.2

File hashes

Hashes for pyft8-0.1.0.tar.gz
Algorithm Hash digest
SHA256 431383b0352d6d2e0371ee678cf22b48d8b8c5d2410c9b684ffc7ef7744fa79f
MD5 15c02f16a8fd883462c2ee6550eb9c54
BLAKE2b-256 152411b9ff27b583af3ab58d9dd6a0fcaf76ec13ca0930b0e288cf5c5f207d7e

See more details on using hashes here.

File details

Details for the file pyft8-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pyft8-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 31.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.2

File hashes

Hashes for pyft8-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 02910c51698af982697f2d2bd6d393bf1e5525fc8cfdc37c04e00bc03247a35f
MD5 c930d74fb5736756569da45edd60d14c
BLAKE2b-256 bf7d889c8cda8184f9280e6bf4b2b916d07da79bd5ae1c6b47f24a434355dd64

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page