39 lines
1.7 KiB
Python
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
|
|
|