From 3dc69180828c0a84896b503a0b4bf1aabed561dc Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Thu, 19 Mar 2026 20:01:29 +0100 Subject: [PATCH] [docs](trx-ftx): add README with attribution and architecture diagram Replace FTX_CRATE.md with README.md documenting upstream origins (kgoba/ft8_lib for FT8/FT4, iu8lmc/Decodium-3.0 for FT2) and a Mermaid diagram of the crate architecture. Co-Authored-By: Claude Opus 4.6 Signed-off-by: Stan Grams --- src/decoders/trx-ftx/FTX_CRATE.md | 134 ------------------------------ src/decoders/trx-ftx/README.md | 71 ++++++++++++++++ 2 files changed, 71 insertions(+), 134 deletions(-) delete mode 100644 src/decoders/trx-ftx/FTX_CRATE.md create mode 100644 src/decoders/trx-ftx/README.md diff --git a/src/decoders/trx-ftx/FTX_CRATE.md b/src/decoders/trx-ftx/FTX_CRATE.md deleted file mode 100644 index d789843..0000000 --- a/src/decoders/trx-ftx/FTX_CRATE.md +++ /dev/null @@ -1,134 +0,0 @@ -# trx-ftx: Pure Rust FTx Decoder - -## Goal - -`trx-ftx` is the pure Rust replacement for the old `trx-ft8` C FFI wrapper. -It provides the same public API (`Ft8Decoder`, `Ft8DecodeResult`) so it can -serve as a drop-in decoder implementation. - -## Why - -- Eliminates `cc`/`libc` build dependencies and `unsafe` FFI -- Better tooling integration (rust-analyzer, clippy, miri) -- Easier maintenance: one language, one build system -- Estimated ~5,350 lines of Rust vs ~7,900 lines of C - -## Crate Structure - -``` -src/decoders/trx-ftx/ - Cargo.toml - FTX_CRATE.md # This file - src/ - lib.rs # Re-exports Ft8Decoder, Ft8DecodeResult - protocol.rs # FtxProtocol enum, timing constants, LDPC params - constants.rs # Costas arrays, LDPC matrices, Gray maps, XOR sequence - crc.rs # CRC-14 (poly 0x2757) - text.rs # Character tables, string utilities - ldpc.rs # Belief propagation + sum-product LDPC decoders - encode.rs # LDPC encoding, Gray mapping, Costas sync insertion - message.rs # Message pack/unpack (all FTx message types) - callsign_hash.rs # Open-addressing hash table for callsign lookup - monitor.rs # Windowed FFT waterfall/spectrogram (Hann window) - decode.rs # Candidate search, sync scoring, likelihood extraction - decoder.rs # Top-level Ft8Decoder (public API) - ft2/ - mod.rs # FT2 pipeline orchestration - downsample.rs # Freq-domain downsampling via IFFT - sync.rs # 2D sync scoring with complex reference waveforms - bitmetrics.rs # Per-symbol FFT, multi-scale bit metrics - osd.rs # OSD-1/OSD-2 CRC-guided decoder - tests/ - decode_ft8_wav.rs # Integration tests with WAV fixtures - block_size.rs # Block size compatibility test -``` - -## Dependencies - -```toml -[dependencies] -rustfft = "6" # SIMD-optimized FFT -realfft = "3" # Real-to-complex FFT wrapper -num-complex = "0.4" # Complex32 type - -[dev-dependencies] -hound = "3" # WAV file reading for integration tests -``` - -## Implementation Phases - -### Phase 1: Foundation (no FFT, no inter-module deps) -1. `protocol.rs` - FtxProtocol enum with timing/parameter methods -2. `constants.rs` - All lookup tables as const arrays -3. `crc.rs` - CRC-14 compute/extract/add -4. `text.rs` - Character tables, string utilities -5. `ldpc.rs` - BP + sum-product decoders with fast tanh/atanh -6. `encode.rs` - LDPC encoding + tone generation -7. `message.rs` - Pack/unpack for all FTx message types -8. `callsign_hash.rs` - Hash table for callsign dedup/lookup - -### Phase 2: DSP (FFT-dependent) -9. `monitor.rs` - Waterfall engine using realfft/rustfft - -### Phase 3: Decode Pipeline -10. `decode.rs` - Candidate search + FT8/FT4/FT2 likelihood extraction -11. `ft2/` - FT2-specific multi-pass pipeline: - - `downsample.rs` - Freq-domain bandpass + IFFT - - `sync.rs` - 2D sync scoring with Costas waveforms - - `bitmetrics.rs` - Multi-scale bit metrics (1/2/4-symbol) - - `osd.rs` - OSD-1/OSD-2 bit-flip search - -### Phase 4: Public API -12. `decoder.rs` - Ft8Decoder struct (matches trx-ft8 API exactly) -13. `lib.rs` - Re-exports - -### Phase 5: Migration -14. Convert `trx-ft8` to thin re-export of `trx-ftx` -15. Delete C sources: `ft8_wrapper.c`, `ft2_ldpc.c`, `build.rs` -16. Remove the vendored `ft8_lib` checkout after the port is complete - -## Historical C Sources Ported - -| C Source | Rust Target | Lines | -|----------|-------------|-------| -| `ft8_lib/ft8/message.c` | `message.rs` | 1156 | -| `src/decoders/trx-ft8/src/ft8_wrapper.c` | `decoder.rs` + `ft2/` | 1800 | -| `ft8_lib/ft8/decode.c` | `decode.rs` | 773 | -| `ft8_lib/ft8/constants.c` | `constants.rs` | 391 | -| `ft8_lib/ft8/text.c` | `text.rs` | 303 | -| `ft8_lib/common/monitor.c` | `monitor.rs` | 261 | -| `ft8_lib/ft8/ldpc.c` | `ldpc.rs` | 251 | -| `ft8_lib/ft8/encode.c` | `encode.rs` | 200 | -| `ft8_lib/ft8/crc.c` | `crc.rs` | 63 | -| `ft8_lib/fft/*.c` | replaced by `rustfft` | 555 | - -## Public API (matches trx-ft8 exactly) - -```rust -pub struct Ft8DecodeResult { - pub text: String, - pub snr_db: f32, - pub dt_s: f32, - pub freq_hz: f32, -} - -pub struct Ft8Decoder { .. } - -impl Ft8Decoder { - pub fn new(sample_rate: u32) -> Result; - pub fn new_ft4(sample_rate: u32) -> Result; - pub fn new_ft2(sample_rate: u32) -> Result; - pub fn block_size(&self) -> usize; - pub fn sample_rate(&self) -> u32; - pub fn window_samples(&self) -> usize; - pub fn reset(&mut self); - pub fn process_block(&mut self, block: &[f32]); - pub fn decode_if_ready(&mut self, max_results: usize) -> Vec; -} -``` - -## Testing Strategy - -- Unit tests per module: CRC round-trip, LDPC recovery, message pack/unpack -- Integration tests: decode reference WAV fixtures when available -- Compatibility test: `ft2_uses_distinct_block_size` (FT4=576, FT2=288, window=45000) diff --git a/src/decoders/trx-ftx/README.md b/src/decoders/trx-ftx/README.md new file mode 100644 index 0000000..81a5755 --- /dev/null +++ b/src/decoders/trx-ftx/README.md @@ -0,0 +1,71 @@ +# trx-ftx + +Pure Rust FT8/FT4/FT2 decoder and encoder library. + +## Attribution + +The FT8 and FT4 implementation is derived from +[kgoba/ft8_lib](https://github.com/kgoba/ft8_lib), a lightweight C +implementation of the FT8/FT4 protocols. + +The FT2 implementation is based on the Fortran reference code in +[iu8lmc/Decodium-3.0-Codename-Raptor](https://github.com/iu8lmc/Decodium-3.0-Codename-Raptor). +FT2 is an experimental protocol that doubles FT4's symbol rate +(NSPS=288, 41.67 baud) while reusing the same LDPC(174,91) code and +4-GFSK modulation with four 4x4 Costas sync arrays. + +## Architecture + +```mermaid +graph TD + subgraph "Shared Modules" + protocol[protocol.rs
FTx constants & timing] + constants[constants.rs
LDPC tables, Costas patterns] + crc[crc.rs
CRC-14] + ldpc[ldpc.rs
Sum-product & BP decoders] + encode[encode.rs
LDPC encoder, tone generation] + message[message.rs
Pack/unpack 77-bit messages] + text[text.rs
Callsign & grid formatting] + callsign_hash[callsign_hash.rs
Hash table for callsign lookup] + end + + subgraph "FT8 / FT4 Pipeline" + monitor[monitor.rs
Waterfall FFT & peak search] + decode[decode.rs
Sync, bit metrics, LDPC decode] + decoder[decoder.rs
Public API: Ft8Decoder] + end + + subgraph "FT2 Pipeline" + ft2_mod[ft2/mod.rs
Pipeline orchestration] + ft2_ds[ft2/downsample.rs
Frequency-shift & downsample] + ft2_sync[ft2/sync.rs
2D Costas correlation] + ft2_bm[ft2/bitmetrics.rs
Multi-scale soft metrics] + ft2_osd[ft2/osd.rs
BP + OSD-1/OSD-2 decoder] + end + + decoder --> monitor --> decode + decode --> ldpc & crc & encode & message & constants + + ft2_mod --> ft2_ds & ft2_sync & ft2_bm & ft2_osd + ft2_osd --> constants & crc & encode + ft2_mod --> decode + decode --> protocol + ft2_mod --> protocol +``` + +### Signal flow + +**FT8/FT4:** Audio samples enter `monitor.rs` which accumulates a +waterfall spectrogram. `decode.rs` finds sync candidates via Costas +correlation, extracts log-likelihood ratios from tone amplitudes, and +runs the LDPC decoder. Decoded 77-bit messages are unpacked by +`message.rs`. + +**FT2:** Audio enters `ft2/mod.rs` which drives a dedicated pipeline: +peak search in the averaged spectrum, frequency-shift downsampling +(`downsample.rs`), 2D sync scoring against precomputed Costas +reference waveforms (`sync.rs`), multi-scale coherent bit metric +extraction at 1/2/4-symbol integration depths (`bitmetrics.rs`), and +multi-pass LDPC decoding via iterative belief-propagation with OSD +fallback (`osd.rs`). The shared `encode.rs`, `crc.rs`, and +`constants.rs` modules are reused across all three protocols.