Files
galileo/docs/boc_aware_lock_detector.md
T

3.3 KiB

BOC-aware code-lock detector

Root cause

The previous code-lock flag compared an instantaneous Prompt power with the mean Early/Late power:

[ M_{legacy}=\frac{|P|^2}{(|E|^2+|L|^2)/2}. ]

That ratio assumes a single-peaked BPSK autocorrelation. It is not a valid lock predicate for the BOC(1,1) replica used by this SignalSim checkout and the receiver. With E/L at +/-0.25 chip, the ideal BOC shape at a +0.25-chip local error has normalized tap powers E=1, P=0.0625, and L=0.25, so the legacy metric is 0.1 even though the local phase is still inside the central-peak basin. No threshold on this ratio can distinguish that valid shoulder from a genuine loss across the complete BOC shape.

SignalSim commit 80b2621 selects PRN_ATTRIBUTE_BOC, doubles the nominal chip rate to 2.046 Mchip/s, shifts the E1B/E1C memory-code index every two subchips, and negates the second half. It therefore generates BOC(1,1), not the BOC(6,1) part of full Galileo CBOC. The Python replica follows the same half-chip convention. The validation plot is generated from SignalSim's actual E1B code table, not a fabricated PRN.

Corrected metric

The detector noncoherently averages all five tap powers over a configurable window. It then evaluates:

[ M_{main}=\frac{|E|^2+|P|^2+|L|^2} {|VE|^2+|E|^2+|P|^2+|L|^2+|VL|^2} ]

and

[ M_{side}=\frac{\max(|VE|^2,|VL|^2)}{|E|^2+|P|^2+|L|^2}. ]

Power fractions alone cannot distinguish the negative Prompt sidelobe at a half-chip error. The detector also smooths the carrier-invariant tap-sign term

[ M_{coh}=\frac{\operatorname{Re}{(E+L)P^*}} {|P|(|E|+|L|)}. ]

It is 1 at the ideal main peak, 1/3 at a quarter-chip main shoulder, and 0 at the +/-0.5-chip negative Prompt sidelobe. Outer-tap dominance covers the +/-0.75-chip false-lock cases. Both tests have independent hysteresis.

metric_valid is independent of code_lock. It remains false until the power window is full, and invalid/non-finite integrations do not enter the smoother. The tracker currently rejects incomplete integrations before correlation; a trailing partial block is not measured. At 4.092 MHz there are exactly four samples/chip. At non-integer ratios, the double-precision code NCO maintains a fractional-chip phase while replica chips and the rectangular BOC subcarrier are selected at each sample. There is no unexplained integer sample shift or interpolation filter in the lock calculation.

Lock uses separate entry/exit limits, consecutive confirmations, and sustained failure counting. A signal-power peak hold detects signal disappearance. A sustained outer-tap dominance declares a BOC side-peak condition. A single instantaneous P/E/L crossing cannot clear lock.

All five accumulations span the same samples and use the same replica amplitude, so the shape metrics normalize by their own summed tap power; division by the integration length (or its square for power) cancels exactly. Mixing raw and normalized taps is prohibited. Boundary-crossing 2 ms dumps are valid because two dumps exactly tile each 4 ms primary period; only a truncated final dump is dropped before the detector.

The lock detector does not change PLL, DLL, FLL, carrier NCO, or code NCO states. Its false-lock and true-loss behavior is regression-tested with ideal main-peak, quarter-chip shoulder, outer-tap side-peak, zero-signal, invalid integration, and one-epoch disturbance vectors.