Skip to content

DSSS Primary Use Cases for Code Acquisition Design

Two operating regimes drive the acquisition design. Both are wide-Doppler (the uncertainty far exceeds one code-period's resolution), but they sit at opposite ends of the speed-vs-sensitivity trade, so they pick different methods. The design goal for each is the fastest method that still acquires at the target (Pfa, Pd).


The method palette

Every acquisition method is built from two Doppler primitives — both already shipped in doppler — optionally wrapped in a coarse mixer/tiling layer and a non-coherent layer:

Method doppler API Doppler res / span Integration Use when
Column-FFT (slow-time) dsss.Acquisition 1/(ny·nx) / ±1/(2nx) ny epochs coherent many coherent reps; need the gain
2-D roll (2-D code FFT × signal FFT → 2-D IFFT) spectral.Corr2D / Detector2D 1/nx / ±1/2 1 epoch wide Δf, few reps, enough SNR — whole grid in one 2-D op
Mixer bank caller loop (guide) tiles either, 1/(2nx) step widen Δf at a fine resolution; linear cost
Non-coherent Acquisition(max_noncoh=…) sensitivity past the coherent ceiling N_nc looks data-bit / burst-limited M_coh

The two primitives are exact duals: the roll's resolution (1/nx) equals the column-FFT's span (±1/(2nx)). Roll = coarse + wide from one epoch; column-FFT = fine + narrow from ny coherent epochs. Mixing the input is the continuous-frequency dual of rolling conj(FFT(code)) by integer bins.


Choosing the method — three knobs

  1. Doppler uncertainty Δf vs the native span ±1/(2nx) (= ±1/(2·T_epoch)). Narrow → one column-FFT covers it. Wide → tile with a mixer bank or sweep all bins at once with a 2-D roll.
  2. Coherent epochs M_coh — how many epochs you can integrate coherently, capped by the burst length (UC2) or the data-bit period (UC1). Large → the column-FFT's fine resolution + 10·log10(ny·N) gain is worth its narrow span. Small (≈1) → the column-FFT is wasted; the roll gives the whole grid for the cost of one epoch.
  3. Sensitivity (cn0_dbhz) — can one epoch acquire, or do you need the gain? High C/N0 → roll (fast). Low C/N0 → coherent gain (column-FFT) and/or non-coherent looks (max_noncoh) when the coherent ceiling is the data bit.

Decision table (Δf vs native span × M_coh):

M_coh small (≈1) M_coh large
Δf narrow Acquisition, reps=few Acquisition alone (fine + gain)
Δf wide 2-D roll (one op, all bins) + non-coherent over reps 2-D-roll coarse or mixer-tile, then column-FFT fine; pick by channel-count vs one 2-D op

The cost asymmetry that decides the wide-Δf row: a 2-D roll sweeps all ~Δf/(1/T_epoch) Doppler bins from one epoch, whereas the fine mixer bank runs that many channels, each a Corr2D tile integrating ny epochs and resolving ny× finer bins. So the bank costs roughly ny× more per Doppler window — and measurably more once the finer bin count is included: ≈40× on a 16×2046 (ny=16) grid, ≈10× on a 5×4094 (ny=5) grid — the factor tracks ny (bench_widedoppler.py). The roll pays for it with one epoch's gain and 1/nx (coarse) resolution. So: roll when SNR lets one epoch acquire; column-FFT/mixer when you must buy the coherent gain.


GPS-like always on 1023-chip Gold code

  • Chip rate < 10 MHz
  • Doppler < 25 ppm moves
  • Symbol rate kHz range
  • Data BPSK asynchronous with code
  • Periodic multi-epoch, code-only transmissions
  • Plenty of time to acquire and lock

Regime (illustrative: L1 C/A, Rc = 1.023 MHz, L = 1023, spc = 2): nx = 2046, T_epoch = 1 ms, native span ±500 Hz (one slow-time bin = 1 kHz). 25 ppm of 1.575 GHz ⇒ Doppler ±39 kHz~79× the native span, so decidedly wide. Asynchronous kHz-rate data ⇒ M_coh ≈ 1 on data-bearing stretches; the periodic code-only epochs are the coherent windows (M_coh = pilot epochs).

Approach — sensitivity-driven (time is plentiful):

  • Coherent inner: run Acquisition over the code-only pilot windows for the fine 1/(ny·T_epoch) Doppler and full coherent gain.
  • Non-coherent across: Acquisition(max_noncoh=…) (P1) accumulates looks across the always-on stream — the data-bit ceiling makes this the real sensitivity engine; "plenty of time" means you can spend many looks.
  • Wide Δf: a coarse layer in front — either a mixer bank (~158 channels at 50% overlap for \<1 dB edge loss) or a 2-D roll (~79 Doppler bins in one 2-D op per epoch) — then the column-FFT refines each coarse bin.

Because sensitivity, not latency, is the constraint, the column-FFT + P1 stack is the core; the coarse layer just covers the 25 ppm span.


Burst Transmission

  • Chip rate in MHz, symbol rate in kHz to MHz
  • Doppler < 25 ppm moves
  • 5+ long (rel. to data code) acquisition code repetitions (no data)
  • Payload follows with shorter data code
  • Data synchronous with symbols

Regime (illustrative: Rc = 5 MHz, long acq code L = 2047, spc = 2, carrier 2.4 GHz): nx = 4094, T_epoch ≈ 0.41 ms, native span ±1.2 kHz (2.44 kHz window). 25 ppm ⇒ Doppler ±60 kHz~49× the native span, wide. The unmodulated preamble gives a clean coherent M_coh = R ≥ 5, and the burst is latency-bound: acquire within the ~5-epoch preamble (~2 ms) before the payload.

Approach — speed-driven (latency-bound, wide Δf, few reps):

  • 2-D roll is the fit: one 2-D op per epoch sweeps all ~49 Doppler bins at the coarse 1/nx (2.44 kHz) resolution — ≈10× cheaper on this 5×4094 grid (bench_widedoppler.py) than running ~98 fine mixer channels each integrating 5 epochs, which a 2-ms latency budget cannot afford serially.
  • Refine only if needed: if the despreader's pull-in can't swallow a 2.44 kHz residual, column-FFT over the 5 reps within the winning coarse bin (one channel) for the fine 1/(5·T_epoch) ≈ 490 Hz Doppler.
  • Hand off: the (Doppler bin, code phase) seeds the shipped Despreader on the shorter data code for the synchronous payload.

Here latency and the wide span dominate; the roll's one-epoch coarse sweep beats the coherent bank.


Why these are the fastest — cost model

For a Doppler span Δf requiring C = Δf / (1/T_epoch) native windows:

  • Mixer + column-FFT: C channels, each a Corr2D(ny, nx) tile — C·ny fine bins, full 10·log10(ny·N) coherent gain, but a 2-D FFT over ny epochs per channel.
  • 2-D roll: C coarse bins from one epoch — one forward FFT_nx shared across C inverse FFT_nx — one epoch's gain, 1/nx resolution.

Measured (bench_widedoppler.py): the fine bank is ≈40× the roll on the GPS 16×2046 grid (C=79) and ≈10× on the burst 5×4094 grid (C=49) — it pays for ny× finer bins and ny epochs of integration, so the gap grows with ny. So the choice is gain vs speed at fixed span: spend the compute (and ny epochs of latency) to buy 10·log10(ny) of coherent gain (UC1, sensitivity-bound), or take the one-epoch roll when the SNR already supports a single-epoch detection (UC2, latency-bound). The non-coherent layer (P1) extends UC1's reach when the coherent ceiling is the data bit. See Benchmarking.


See also