Add BOC-aware lock detection and E1C-aided tracking
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user