016c (1/2): Galileo E5a/E5b primary codes + QPSK(10) I/Q generator (ICD-validated 200/200) #22

Merged
ykp merged 2 commits from feat/016c-galileo into main 2026-09-24 08:30:46 +02:00
Owner

First increment of backlog step 016c (Galileo E1/E5 + GLONASS CDMA).

Data provenance - Galileo OS SIS ICD v2.1 (Nov 2023) fetched from GSC
(5.4 MB, 128 pages). The E5 primary codes are fully specified there:

  • ICD Table 15: two 14-stage LFSRs per component; taps (octal)
    E5a-I/E5a-Q: R1=40503 R2=50661; E5b-I: R1=64021 R2=51445;
    E5b-Q: R1=64021 R2=43143; R1 start = all ones; code = R1 XOR R2,
    truncated to 10230 chips (10.23 Mcps, 1 ms period)
  • ICD Tables 16-19: base register 2 start values (octal) + first-24-chips
    (hex) per PRN, 50 PRNs per component, extracted per row and VALIDATED
    against the initial-sequence columns: 200/200 reproduce
  • Register conventions were fitted from the ICD example (E5a-I PRN1,
    3CEA9D) and confirmed on all 200 rows: content shifts toward higher j,
    output at c[14], feedback (XOR of tapped cells) enters at c[1], start
    value loaded MSB-first into c[1..R] (documented in codes.py)

Implementation

  • codes.py: GAL_E5_TAPS, GAL_E5_R2_STARTS (200 baked rows),
    _gal_e5_register, galileo_e5_code(prn, component) - bipolar output
  • generator.py: gal_e5a/gal_e5b as QPSK(10) I/Q pairs (I = E5x-I data,
    Q = E5x-Q pilot) via a plain-qpsk data mode; secondary codes deferred
  • signals.py: gal_e5a/gal_e5b flipped to Tier 1
  • harness: gal_e5a/gal_e5b replicas (I code)
  • README Tier-1 matrix refreshed (was still at v0.1.0 state)

Deferred (documented):

  • Galileo E1-B/E1-C primary codes: the ICD v2.1 states they are memory
    codes provided ONLY in the electronic Annex C - not in the PDF
  • E5/E1 secondary codes (Tables 20/21): next increment
  • GLONASS CDMA (L1OCp/L2OCp/L3OC): ICD appendices 403-gated - document
    as infeasible unless a public source surfaces
  • Full AltBOC(15,10) modulation: the registry stays QPSK(10) SSB for now

Tests (7): ICD PRN-1 example, all 200 baked rows re-validated
in-process, component distinctness, period/alphabet, unknown-PRN/component
errors, E5a I recovery, E5b Q recovery.

Local verification: pytest 169 passed + 1 gui skip, ruff clean (Python 3.14).

Note (process): NOT to be merged by automation - awaiting manual review/merge.

First increment of backlog step 016c (Galileo E1/E5 + GLONASS CDMA). **Data provenance** - Galileo OS SIS ICD v2.1 (Nov 2023) fetched from GSC (5.4 MB, 128 pages). The E5 primary codes are fully specified there: - ICD Table 15: two 14-stage LFSRs per component; taps (octal) E5a-I/E5a-Q: R1=40503 R2=50661; E5b-I: R1=64021 R2=51445; E5b-Q: R1=64021 R2=43143; R1 start = all ones; code = R1 XOR R2, truncated to 10230 chips (10.23 Mcps, 1 ms period) - ICD Tables 16-19: base register 2 start values (octal) + first-24-chips (hex) per PRN, 50 PRNs per component, extracted per row and VALIDATED against the initial-sequence columns: 200/200 reproduce - Register conventions were fitted from the ICD example (E5a-I PRN1, 3CEA9D) and confirmed on all 200 rows: content shifts toward higher j, output at c[14], feedback (XOR of tapped cells) enters at c[1], start value loaded MSB-first into c[1..R] (documented in codes.py) **Implementation** - codes.py: GAL_E5_TAPS, GAL_E5_R2_STARTS (200 baked rows), _gal_e5_register, galileo_e5_code(prn, component) - bipolar output - generator.py: gal_e5a/gal_e5b as QPSK(10) I/Q pairs (I = E5x-I data, Q = E5x-Q pilot) via a plain-qpsk data mode; secondary codes deferred - signals.py: gal_e5a/gal_e5b flipped to Tier 1 - harness: gal_e5a/gal_e5b replicas (I code) - README Tier-1 matrix refreshed (was still at v0.1.0 state) **Deferred (documented):** - Galileo E1-B/E1-C primary codes: the ICD v2.1 states they are memory codes provided ONLY in the electronic Annex C - not in the PDF - E5/E1 secondary codes (Tables 20/21): next increment - GLONASS CDMA (L1OCp/L2OCp/L3OC): ICD appendices 403-gated - document as infeasible unless a public source surfaces - Full AltBOC(15,10) modulation: the registry stays QPSK(10) SSB for now **Tests** (7): ICD PRN-1 example, all 200 baked rows re-validated in-process, component distinctness, period/alphabet, unknown-PRN/component errors, E5a I recovery, E5b Q recovery. Local verification: pytest 169 passed + 1 gui skip, ruff clean (Python 3.14). Note (process): NOT to be merged by automation - awaiting manual review/merge.
016c(core): Galileo E5a/E5b primary codes (ICD Tables 15-19, 200/200 validated) + QPSK(10) I/Q generator, tier flip
Some checks failed
ci / test (3.12) (push) Failing after 3m8s
ci / test (3.14) (push) Successful in 4m1s
ci / test (3.12) (pull_request) Successful in 1m28s
ci / test (3.14) (pull_request) Has been cancelled
d72197062b
016c(ci): retrigger (py3.12 push job failed without logs; local + py3.14 green)
All checks were successful
ci / test (3.12) (push) Successful in 1m46s
ci / test (3.14) (push) Successful in 1m44s
ci / test (3.12) (pull_request) Successful in 2m38s
ci / test (3.14) (pull_request) Successful in 2m41s
e6fde03901
ykp merged commit a2e81738e9 into main 2026-09-24 08:30:46 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
ykp/gengnss!22
No description provided.