1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! # `engine` — protocol traits, DSP, sync, pipeline
//!
//! Generic MFSK (M-ary frequency-shift-keying) primitives for WSJT-family
//! amateur-radio digital modes (FT8, FT4, FT2, FST4, JT9, JT65, WSPR).
//!
//! This module defines *protocol traits* whose associated constants describe
//! modulation / frame / FEC / message-codec parameters, plus generic pipeline
//! code parameterised by those traits. Per-protocol modules ([`crate::ft8`],
//! [`crate::ft4`], …) provide zero-sized types that implement the traits — all
//! dispatch is monomorphised, so there is no runtime cost vs. hand-written
//! per-protocol code.
//!
//! ## Zero-cost dispatch philosophy
//!
//! - **Hot paths** (sync correlation, LLR, FEC inner loops, DSP) take
//! `P: Protocol` as a compile-time type parameter. Each concrete protocol
//! produces its own monomorphised copy — LLVM sees a fully-specialised
//! function and can autovectorise / drop bounds checks.
//! - **Cold paths** (message codec callbacks, CLI glue, FFI boundary) may
//! legitimately use `dyn MessageCodec` / `Box<dyn …>` where ergonomics
//! beat the negligible virtual-call cost.
//!
//! ## Re-export layout
//!
//! Commonly-used types (`Protocol`, `ModulationParams`, `FrameLayout`,
//! `FecCodec`, `MessageCodec`, `ProtocolId`, `SyncMode`, `SyncBlock`,
//! `DecodeContext`, `FecOpts`, `FecResult`, `MessageFields`) are also
//! re-exported at the crate root for ergonomics.
// Pure bit-permutation, no FFT/complex-number dependency — ungated
// like `protocol`/`tx`/`scalar` so embedded TX-only builds can use it
// too (WSPR's own TX path is a potential future consumer).
// Decode-side modules go through the `engine::fft` trait abstraction;
// gated on the meta-feature (true if any of fft-rustfft / fft-microfft
// / fft-extern is on). Embedded TX-only builds with no FFT backend
// still get `protocol`, `tx`, equalize, and the synthesis-side dsp
// helpers (gfsk, resample, subtract).
// Hardcodes `rustfft::FftPlanner` directly (matching what JT9/JT65/Q65
// already did before this was extracted) rather than routing through
// the `engine::fft` backend-abstraction trait `sync`/`llr`/`pipeline`
// use — those three protocols' own Cargo features already require
// `fft-rustfft` specifically (`jt9`/`jt65`/`q65` = [.., "fft-rustfft"]
// in Cargo.toml, no `fft-extern` alternative), so this gate changes
// nothing about what builds succeed.
pub use ;