pub fn generate_ofdm_preamble(
preamble: &OfdmPreamble,
cfg: &OfdmConfig,
) -> Vec<Complex32> ⓘExpand description
Generates a repeated-segment preamble: a deterministic, reproducible
pseudo-random unit-average-energy base sequence of repeat_len samples,
tiled num_repeats times, followed by the training symbol (time-domain,
CP included) if preamble.training_symbol is present.
The repeat base sequence and the training symbol’s frequency-domain
pattern are both generated from fixed seeds (not derived from cfg), so
the same OfdmPreamble always produces the same preamble on both the TX
and RX side without requiring shared external state.
cfg.gain is applied to the result, exactly as OfdmMod applies it
to every data symbol. This is not cosmetic: the preamble and the payload
must share one amplitude scale or the frame is undecodable.
- The Schmidl & Cox timing metric normalizes against received energy, so a
preamble that is quiet relative to the payload collapses the score. At
gain = 121with an unscaled preamble the best score falls from 1.00 to 0.095 — below the streaming receiver’s 0.5 acceptance threshold, so no candidate is ever accepted and nothing decodes. EqualizerMethod::TrainingSymbolHoldestimates the channel from the training symbol. If the training symbol is unscaled while the payload is not, the estimate omits the gain, the equalizer never divides it out, and the demapper’s LLRs are miscalibrated by that factor.
cfg’s other fields remain unused here. In particular rf_hz is still
not applied — a caller using a nonzero rf_hz gets a baseband preamble
ahead of an upconverted body. Applying it correctly requires phase
continuity with the symbols that follow, which the per-block modulator
construction does not currently provide; modulate at rf_hz = 0.0 and
upconvert the whole burst with one continuous
Rotator instead.