""" Apollo Ranging Source -- streams PRN ranging chips. Outputs a continuous stream of bytes (0 or 1) representing the composite PRN ranging code. The code repeats every 5,456,682 chips (~5.49 seconds at the nominal 993,963 chip/s rate). The full code period is pre-generated and cycled through, so startup cost is paid once and streaming is zero-allocation. Reference: Ken Shirriff's Apollo ranging analysis http://www.righto.com/2022/04/the-digital-ranging-system-that.html """ import numpy as np from apollo.ranging import RANGING_CODE_LENGTH, RangingCodeGenerator # --------------------------------------------------------------------------- # GNU Radio block (optional -- only if gnuradio is available) # --------------------------------------------------------------------------- try: from gnuradio import gr class ranging_source(gr.sync_block): """GNU Radio source: continuous PRN ranging chip stream. Outputs bytes (0 or 1) at the chip rate. Pre-generates the full code period and cycles through it. """ def __init__(self): gr.sync_block.__init__( self, name="apollo_ranging_source", in_sig=None, out_sig=[np.byte], ) self._gen = RangingCodeGenerator() self._code = self._gen.generate_sequence() self._pos = 0 def work(self, input_items, output_items): out = output_items[0] n = len(out) produced = 0 while produced < n: remaining = RANGING_CODE_LENGTH - self._pos chunk = min(n - produced, remaining) out[produced : produced + chunk] = self._code[self._pos : self._pos + chunk] self._pos = (self._pos + chunk) % RANGING_CODE_LENGTH produced += chunk return produced except ImportError: pass