Files
galileo/src/galileo_rx/signals/boc.py
T

39 lines
1.7 KiB
Python

"""BOC modulation helpers with sample-continuous phase."""
from __future__ import annotations
import numpy as np
import numpy.typing as npt
def boc_subcarrier(
sample_count: int,
sampling_frequency_hz: float,
subcarrier_frequency_hz: float,
initial_phase_cycles: float = 0.0,
) -> tuple[npt.NDArray[np.float64], float]:
"""Generate sine-phased square-wave BOC subcarrier and ending phase in cycles."""
if sample_count < 0 or sampling_frequency_hz <= 0 or subcarrier_frequency_hz <= 0:
raise ValueError("invalid BOC generator parameters")
phase = initial_phase_cycles + np.arange(sample_count, dtype=np.float64) * subcarrier_frequency_hz / sampling_frequency_hz
wave = np.where(np.mod(phase, 1.0) < 0.5, 1.0, -1.0)
ending_phase = float((initial_phase_cycles + sample_count * subcarrier_frequency_hz / sampling_frequency_hz) % 1.0)
return wave, ending_phase
def sample_primary_code(
code: npt.NDArray[np.int8],
sample_count: int,
sampling_frequency_hz: float,
code_rate_hz: float,
initial_code_phase_chips: float = 0.0,
) -> tuple[npt.NDArray[np.float64], float]:
"""Nearest-chip code sampling supporting noninteger samples per chip."""
if code.ndim != 1 or code.size == 0 or sampling_frequency_hz <= 0 or code_rate_hz <= 0:
raise ValueError("invalid code sampling parameters")
phases = initial_code_phase_chips + np.arange(sample_count, dtype=np.float64) * code_rate_hz / sampling_frequency_hz
values = code[np.floor(phases).astype(np.int64) % code.size].astype(np.float64)
ending_phase = float((initial_code_phase_chips + sample_count * code_rate_hz / sampling_frequency_hz) % code.size)
return values, ending_phase