from __future__ import annotations import numpy as np from galileo_rx.navigation.e1b_symbol_sync import NavigationSymbol from galileo_rx.navigation.inav_page_sync import INAV_SYNC_BITS, InavPageSynchronizer def _symbols(bits: np.ndarray, *, invert: bool = False, prefix: int = 17) -> list[NavigationSymbol]: raw = np.concatenate((np.zeros(prefix, dtype=np.int8), bits)) if invert: raw = 1 - raw return [NavigationSymbol(1, i, i * 4, (i + 1) * 4, 1.0 if bit else -1.0, int(bit), 1.0, False, True) for i, bit in enumerate(raw)] def test_page_sync_rejects_wrong_boundary_and_requires_repetition() -> None: rng = np.random.default_rng(4) part = np.concatenate((INAV_SYNC_BITS, rng.integers(0, 2, 240, dtype=np.int8))) stream = _symbols(np.tile(part, 3)) sync = InavPageSynchronizer(required_confirmations=2) first = sync.process_many(stream[:267]) assert first == [] output = sync.process_many(stream[267:]) assert len(output) == 3 assert all(item.sync_valid for item in output) def test_page_sync_records_global_inversion() -> None: body = np.zeros(240, dtype=np.int8) parts = InavPageSynchronizer().process_many(_symbols(np.tile(np.concatenate((INAV_SYNC_BITS, body)), 3), invert=True)) assert len(parts) == 3 assert all(item.polarity_inverted for item in parts) assert np.array_equal(parts[0].hard_symbols[:10], INAV_SYNC_BITS) def test_page_sync_loses_and_reacquires_after_corrupted_sync() -> None: body = np.zeros(240, dtype=np.int8) part = np.concatenate((INAV_SYNC_BITS, body)) bits = np.tile(part, 6) bits[3 * 250] ^= 1 output = InavPageSynchronizer().process_many(_symbols(bits, prefix=0)) assert len(output) == 5 assert [item.receive_sample_timestamp // (250 * 4) for item in output] == [0, 1, 2, 4, 5] def test_page_sync_does_not_lock_through_symbol_erasure() -> None: body = np.zeros(240, dtype=np.int8) symbols = _symbols(np.tile(np.concatenate((INAV_SYNC_BITS, body)), 3), prefix=0) erased = symbols[250] symbols[250] = NavigationSymbol( erased.prn, erased.symbol_index, erased.start_sample_timestamp, erased.end_sample_timestamp, 0.0, 0, 0.0, False, False, ) assert InavPageSynchronizer().process_many(symbols) == []