""" Apollo BPSK Subcarrier Demodulator — convenience wrapper. Hierarchical block combining subcarrier_extract + bpsk_demod into a single block for the common case of extracting and demodulating the 1.024 MHz PCM subcarrier from the PM demodulator output. This resolves the naming used in __init__.py and provides a simple "float in, bytes out" interface. Reference: IMPLEMENTATION_SPEC.md section 4.2 """ from gnuradio import gr from apollo.bpsk_demod import bpsk_demod from apollo.constants import PCM_BPF_BW_HZ, PCM_HIGH_BIT_RATE, PCM_SUBCARRIER_HZ from apollo.subcarrier_extract import subcarrier_extract class bpsk_subcarrier_demod(gr.hier_block2): """Combined subcarrier extraction + BPSK demodulation. Inputs: float — PM demodulator output (composite subcarrier signal) Outputs: byte — recovered NRZ bits (0 or 1) """ def __init__( self, subcarrier_freq: float = PCM_SUBCARRIER_HZ, bandwidth: float = PCM_BPF_BW_HZ, bit_rate: float = PCM_HIGH_BIT_RATE, sample_rate: float = 5_120_000, decimation: int = 1, loop_bw: float = 0.045, ): gr.hier_block2.__init__( self, "apollo_bpsk_subcarrier_demod", gr.io_signature(1, 1, gr.sizeof_float), gr.io_signature(1, 1, gr.sizeof_char), ) # Subcarrier extraction: bandpass + translate to baseband self.extract = subcarrier_extract( center_freq=subcarrier_freq, bandwidth=bandwidth, sample_rate=sample_rate, decimation=decimation, ) # BPSK demodulation: carrier recovery + symbol sync + slicer output_rate = sample_rate / decimation self.demod = bpsk_demod( symbol_rate=bit_rate, sample_rate=output_rate, loop_bw=loop_bw, ) # Connect: float input → extract → demod → byte output self.connect(self, self.extract, self.demod, self)