pub trait ModulationParams:
Copy
+ Default
+ 'static {
Show 16 associated constants and 0 method
const NTONES: u32;
const BITS_PER_SYMBOL: u32;
const NSPS: u32;
const SYMBOL_DT: f32;
const TONE_SPACING_HZ: f32;
const GRAY_MAP: &'static [u8];
const GFSK_BT: f32;
const GFSK_HMOD: f32;
const NFFT_PER_SYMBOL_FACTOR: u32;
const NSTEP_PER_SYMBOL: u32;
const NDOWN: u32;
const LLR_SCALE: f32 = 2.83;
const LLR_NSYM_MAX: u32 = 3;
const LLR_NSYM_MID: Option<u32> = None;
const INFO_SCRAMBLE_RVEC: Option<&'static [u8]> = None;
const SPECTRUM_WINDOW: SpectrumWindow = SpectrumWindow::Rectangular;
}Expand description
Baseband modulation parameters (tones, symbol rate, Gray mapping, Gaussian shaping and the tunable DSP ratios the pipeline reads per protocol).
All constants are evaluated at compile time; the trait carries no data so implementors are typically zero-sized types.
Required Associated Constants§
Sourceconst BITS_PER_SYMBOL: u32
const BITS_PER_SYMBOL: u32
Information bits carried per modulated symbol (= log2(NTONES)).
Sourceconst TONE_SPACING_HZ: f32
const TONE_SPACING_HZ: f32
Spacing between adjacent tones, in Hz.
Sourceconst GRAY_MAP: &'static [u8]
const GRAY_MAP: &'static [u8]
Gray-code map: GRAY_MAP[tone_index] returns the NATURAL-bit pattern
for that tone. The map covers at least the data alphabet
(2^BITS_PER_SYMBOL entries) and at most the full tone set
(NTONES entries). Protocols whose sync tones are part of
the data alphabet (FT8 / FT4 / FST4 / WSPR) have
len() == NTONES == 2^BITS_PER_SYMBOL; protocols that
reserve additional sync-only tones (JT9, JT65, Q65) either
trim the map to the data alphabet (JT9: 8 entries for 9
tones) or extend it with identity over the sync slots
(JT65 / Q65). Pinned by tests/protocol_invariants.rs.
Sourceconst GFSK_HMOD: f32
const GFSK_HMOD: f32
Modulation index h — the phase increment per symbol is 2π · h.
FT8 and FT4 both use 1.0 (orthogonal tones at 1/T spacing).
Sourceconst NFFT_PER_SYMBOL_FACTOR: u32
const NFFT_PER_SYMBOL_FACTOR: u32
Per-symbol FFT size = NSPS * NFFT_PER_SYMBOL_FACTOR.
FT8 = 2 (window is 2·NSPS), FT4 = 4 (window is 4·NSPS) — trade-off
between frequency resolution and time localisation.
Sourceconst NSTEP_PER_SYMBOL: u32
const NSTEP_PER_SYMBOL: u32
Coarse-sync time-step = NSPS / NSTEP_PER_SYMBOL.
FT8 = 4 (quarter-symbol resolution), FT4 = 1 (symbol-granular).
Provided Associated Constants§
Sourceconst LLR_SCALE: f32 = 2.83
const LLR_SCALE: f32 = 2.83
LLR scale factor applied after standard-deviation normalisation. FT8 uses 2.83 (empirical, from WSJT-X ft8b.f90). Different bits-per-symbol counts may shift the optimum — FT4’s 2-bit LLR dynamics are not identical to FT8’s 3-bit case.
Sourceconst LLR_NSYM_MAX: u32 = 3
const LLR_NSYM_MAX: u32 = 3
Maximum coherent-integration depth for the 3rd LLR variant.
compute_llr builds three variants llra/llrb/llrc from
nsym ∈ {1, 2, LLR_NSYM_MAX} symbol blocks. WSJT-X uses
nsym=1, 2, 4 for FT4 (get_ft4_bitmetrics.f90:69-71); we
default to nsym=3 (FT8 path is calibrated to it). FT4
overrides to 4 for an extra ~3 dB SNR boost on stable
signals — closes the recall gap on real-WAV recordings. FST4
overrides to 8, matching WSJT-X’s own 1/2/4/8-symbol
correlation ladder in get_fst4_bitmetrics.f90 (issue #146 —
FST4 had silently been using the uncalibrated FT8 default of
3, never wired to its own bit-metric depth).
Any value ≥ 1 works — nt = NTONES^nsym combination
hypotheses are computed generically, no per-nsym lookup table
— but cost grows exponentially with nsym, so keep it at the
WSJT-X-matched depth for the protocol rather than raising it
further.
Sourceconst LLR_NSYM_MID: Option<u32> = None
const LLR_NSYM_MID: Option<u32> = None
Optional extra coherent-integration depth strictly between the
nsym=2 and nsym=LLR_NSYM_MAX variants, populating LlrSet’s
llre slot. None for every protocol whose ladder has no gap
(FT8: {1,2,3}; FT4: {1,2,4}) — llre stays empty and costs
nothing. FST4 overrides to Some(4): WSJT-X’s
get_fst4_bitmetrics.f90 tries all four of nsym ∈ {1,2,4,8}
(fst4_decode.f90:429-433), but LLR_NSYM_MAX=8 alone only
gives compute_llr_generic two depths + the deepest ({1,2,8}) —
nsym=4 would otherwise never run. Diagnostic measurement (issue
#146, fst4_diag_nsym4_ladder in tests/fst4_sweep.rs) found a
real but modest effect: a standalone nsym=4 pass recovered 4/43
(~9%) of near-threshold FST4-30 AWGN failures and 2/38 (~5%) of
FST4-300’s, over and above the existing {1,2,8,d} ladder.
Sourceconst INFO_SCRAMBLE_RVEC: Option<&'static [u8]> = None
const INFO_SCRAMBLE_RVEC: Option<&'static [u8]> = None
Optional 77-bit pre-LDPC scrambler. WSJT-X applies an
FT4-specific scrambler in genft4.f90:64
(msgbits=mod(msgbits+rvec,2)) before computing CRC-14 and
running LDPC encode; the receiver removes it after LDPC
decode + CRC verify (ft4_decode.f90:430). Without this our
decoder converges on a valid codeword whose unscrambled
payload is the WSJT-X-transmitted message — but emerges as
nonsense because we never undo the XOR.
Default None (FT8 / others don’t scramble); FT4 and FST4
both override to the same 77-element rvec (WSJT-X
genfst4.f90:29-31 uses the identical array to
genft4.f90’s). Length must be 77 when set.
Sourceconst SPECTRUM_WINDOW: SpectrumWindow = SpectrumWindow::Rectangular
const SPECTRUM_WINDOW: SpectrumWindow = SpectrumWindow::Rectangular
Window function applied per NSPS-sample chunk in
crate::core::sync::compute_spectra before the NFFT1 FFT.
Default = SpectrumWindow::Rectangular (preserves FT8’s
existing synth-roundtrip behaviour); FT4 overrides to
SpectrumWindow::Nuttall4 to match WSJT-X
getcandidates4.f90:22 and suppress sidelobe leakage that
otherwise inflates the per-bin baseline near strong signals.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".