You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Proposal to extend the LUT code generators (CodeReplicaLUT / CodeGeneratorLUT / CodeGeneratorLUT4) to support Galileo E1B (CBOC) by baking a multi-level Int8 sub-chip table instead of the current ±1-only table. CBOC is the one remaining signal the LUT path rejects; the obstacle is not fundamental.
Background
_codelut_modulation currently throws for CBOC:
function_codelut_modulation(m::CBOC)
error("CodeReplicaLUT does not support CBOC (Int8/±1 only); use gen_code!")
end
CBOC(6,1,1/11) (Galileo E1B, boc1_power = 10/11) has subcarrier √(10/11)·BOC(1,1) ± √(1/11)·BOC(6,1), so each sub-chip takes one of four values rather than ±1:
±1.25497 when the two BOC signs agree
±0.65195 when they disagree
That 4-level structure (not the irrational amplitudes per se) is why it breaks the LUT's ±1 assumption (_sc_sign returns Int8(±1); primary/secondary multiplies are ±1; get_code_type(GalileoE1B()) === Float32).
Why this is feasible
CodeTable stores Int8 chips verbatim and the permute/run-fill kernels just shuffle bytes — multi-level values are mechanically fine. The only quantity that must be right is the level ratio A/B ≈ (a+b)/(a-b) = 1.924951 (overall scale cancels in correlation).
Quantization quality with small Int8 levels (relative RMS error of the quantized waveform vs the exact float CBOC, optimized over scale):
Int8 levels
ratio
rel. RMS waveform error
±2 / ±1
2.000
1.55 %
±25 / ±13
1.9231
0.040 %
±27 / ±14
1.9286
0.077 %
±77 / ±40
1.92500
0.0011 %
±77 / ±40 (both within Int8) matches the ratio to 0.0026% → ~0.001% RMS waveform error, i.e. negligible correlation loss, far below any receiver's quantization/noise floor.
Reproduction of the table:
a =sqrt(10/11); b =sqrt(1/11); hi = a + b; lo = a - b
r = hi/lo # 1.924950591148529waveform_err(A, B) =begin
tv = Float64[hi, lo, -lo, -hi]; qv = Float64[A, B, -B, -A]
c =sum(tv .* qv) /sum(qv .^2) # least-squares scalesqrt(sum((tv .- c .* qv) .^2) /sum(tv .^2))
endwaveform_err(77, 40) # ≈ 1.05e-5
Proposed change
Add a CBOC arm to _codelut_modulation and a CodeLUT.CBOC modulation descriptor with subchip_factor = 2·m2 = 12 (BOC(6,1) sets the resolution).
A CBOC-specific _sc_sign-style baker producing the 4 levels per sub-chip: level(k, pos, P) = s1 · (s1 == s2 ? A : B), where s1 is the BOC(1,1) sub-chip sign and s2 the BOC(6,1) sub-chip sign, with A/B a chosen rational (default ±77/±40).
The primary chip (±1) and any secondary (±1) multiply the baked level as today — sign flips preserve the level structure, so it composes with the existing primary/secondary path unchanged.
Caveats / decisions to make
Output convention: the LUT would emit a scaled, multi-levelInt8 replica (magnitudes {77, 40}), not ±1 and not the float path's scale. Correlation is scale-invariant, but callers mixing it with a carrier need wider accumulators (already true for Int8 chips, just larger magnitude). Worth documenting clearly, or exposing the chosen (A, B) on the plan.
Level choice:±25/±13 (0.04 %) keeps magnitudes small (less accumulator growth) and is still excellent; ±77/±40 is essentially exact. Could be a parameter with a sensible default.
Not byte-identical to the existing Float32gen_code!; a test should assert correlation/normalized-shape agreement within a tolerance rather than exact equality.
Summary
Proposal to extend the LUT code generators (
CodeReplicaLUT/CodeGeneratorLUT/CodeGeneratorLUT4) to support Galileo E1B (CBOC) by baking a multi-levelInt8sub-chip table instead of the current ±1-only table. CBOC is the one remaining signal the LUT path rejects; the obstacle is not fundamental.Background
_codelut_modulationcurrently throws for CBOC:CBOC(6,1,1/11) (Galileo E1B,
boc1_power = 10/11) has subcarrier√(10/11)·BOC(1,1) ± √(1/11)·BOC(6,1), so each sub-chip takes one of four values rather than ±1:±1.25497when the two BOC signs agree±0.65195when they disagreeThat 4-level structure (not the irrational amplitudes per se) is why it breaks the LUT's ±1 assumption (
_sc_signreturnsInt8(±1); primary/secondary multiplies are ±1;get_code_type(GalileoE1B()) === Float32).Why this is feasible
CodeTablestoresInt8chips verbatim and the permute/run-fill kernels just shuffle bytes — multi-level values are mechanically fine. The only quantity that must be right is the level ratioA/B ≈ (a+b)/(a-b) = 1.924951(overall scale cancels in correlation).Quantization quality with small
Int8levels (relative RMS error of the quantized waveform vs the exact float CBOC, optimized over scale):±77 / ±40(both withinInt8) matches the ratio to 0.0026% → ~0.001% RMS waveform error, i.e. negligible correlation loss, far below any receiver's quantization/noise floor.Reproduction of the table:
Proposed change
_codelut_modulationand aCodeLUT.CBOCmodulation descriptor withsubchip_factor = 2·m2 = 12(BOC(6,1) sets the resolution)._sc_sign-style baker producing the 4 levels per sub-chip:level(k, pos, P) = s1 · (s1 == s2 ? A : B), wheres1is the BOC(1,1) sub-chip sign ands2the BOC(6,1) sub-chip sign, withA/Ba chosen rational (default±77/±40).Caveats / decisions to make
Int8replica (magnitudes{77, 40}), not ±1 and not the float path's scale. Correlation is scale-invariant, but callers mixing it with a carrier need wider accumulators (already true forInt8chips, just larger magnitude). Worth documenting clearly, or exposing the chosen(A, B)on the plan.±25/±13(0.04 %) keeps magnitudes small (less accumulator growth) and is still excellent;±77/±40is essentially exact. Could be a parameter with a sensible default.Float32gen_code!; a test should assert correlation/normalized-shape agreement within a tolerance rather than exact equality.Cosine-phased
BOCcosis a separate, easier case (it is ±1, just a quarter-chip phase offset) and could be folded in alongside if desired.