8 Commits

Author SHA1 Message Date
78e73ca38c Merge feature/uplink-chain: full DSKY command encode/decode over RF 2026-02-24 14:23:29 -07:00
0e77373ea4 Add uplink chain: DSKY command encoder to RF and back
Uplink word codec (uplink_word_codec.py):
- UplinkSerializerEngine: (channel, value) pairs to 15-bit NRZ bit stream
  with configurable inter-word gap for UPRUPT timing
- UplinkDeserializerEngine: two-phase state machine (acquisition + fixed
  framing) recovers words from NRZ bits, handles leading-zero data words
- GR wrappers: uplink_word_serializer (sync_block source) and
  uplink_word_deserializer (basic_block sink with message output)

TX source (usb_uplink_source.py):
- hier_block2 wiring: word_serializer -> nrz_encoder -> FM mod (4 kHz dev)
  -> 70 kHz upconvert -> complex_to_real -> PM mod (1.0 rad) -> [AWGN]
- Message input "words" forwards PDUs from uplink_encoder

RX receiver (usb_uplink_receiver.py):
- hier_block2 wiring: PM demod -> subcarrier_extract (70 kHz, 20 kHz BW)
  -> quadrature_demod -> matched filter -> decimate -> slicer -> deserializer
- Message output "commands" emits recovered (channel, value) PDUs

GRC block definitions for both source and receiver.

Loopback demo (uplink_loopback_demo.py):
- Encodes V16N36E, serializes with pure-Python engine, runs through GR RF
  chain (FM + PM + noise + demod), deserializes, compares TX vs RX words
2026-02-24 14:17:58 -07:00
77ddec149c Add audio download script and real signal demo
fetch_apollo_audio.py downloads Apollo 11 audio highlights from Archive.org
and extracts clips using ffmpeg (48 kHz mono WAV). Supports --list, --clip,
--all with idempotent downloads and progress reporting.

real_signal_demo.py auto-discovers downloaded clips and runs them through the
full USB downlink TX/RX chain (PCM telemetry + FM voice), saving recovered
audio for comparison. Falls back to the bundled demo clip if no downloads exist.

Also adds .gitignore to keep large audio files out of the repo while preserving
the small apollo11_crew.wav demo clip.
2026-02-24 14:15:23 -07:00
7d48398551 Add FM downlink mode: carrier blocks, convenience wrappers, and loopback demo
FM mode now has the same three-layer architecture as PM mode:
- fm_mod/fm_demod for carrier-level FM modulation
- fm_signal_source/fm_downlink_receiver convenience wrappers
- fm_loopback_demo.py verifying round-trip SCO voltage recovery

Includes GRC YAML for all 4 blocks and doc updates across
blocks reference, SCO guide, and signal architecture pages.
2026-02-24 10:18:42 -07:00
cb77b18a9c Add full downlink demo: PCM telemetry + crew voice on one carrier
Assembles the complete Apollo USB downlink signal from individual blocks:
PCM frames on 1.024 MHz BPSK + crew voice on 1.25 MHz FM, both PM-modulated
onto a single complex carrier. Receives and splits into decoded PCM frames
and recovered voice audio.

Clean: 399/402 frames, 8s voice. At 25 dB SNR: 395/402 frames.
2026-02-22 18:06:22 -07:00
8728d36a90 Add voice subcarrier demo with Apollo 11 crew audio
FM-modulates real Apollo 11 onboard audio onto the 1.25 MHz voice
subcarrier (+/-29 kHz deviation) and demodulates it back, achieving
94.1% correlation with the original. Audio source: NASA/Internet
Archive public domain (Collins bidding farewell to Eagle crew).
2026-02-22 18:00:45 -07:00
cd3a8cc6be Add SCO modulator, external audio input, and demo scripts
- sco_mod: 9-channel FM subcarrier oscillator modulator (inverse of sco_demod),
  with round-trip tests proving voltage recovery across all channels
- fm_voice_subcarrier_mod: add audio_input parameter to accept external float
  streams (e.g., Apollo mission voice recordings) instead of internal test tone
- loopback_demo.py: streaming TX->RX round-trip with CLI for noise/voice/frames
- agc_loopback_demo.py: full Virtual AGC integration via TCP bridge
2026-02-22 13:01:48 -07:00
0ee7ff0ad7 Implement full Apollo USB downlink decoder chain
Complete signal processing pipeline from complex baseband to decoded
PCM telemetry, verified against the 1965 NAA Study Guide (A-624):

Core demod (Phase 1):
  - PM demodulator with carrier PLL recovery
  - 1.024 MHz subcarrier extractor (bandpass + downconvert)
  - BPSK demodulator with Costas loop + symbol sync
  - Convenience hier_block2 combining subcarrier + BPSK

PCM frame processing (Phase 2):
  - 32-bit frame sync with Hamming distance correlator
  - SEARCH/VERIFY/LOCKED state machine, complement-on-odd handling
  - Frame demultiplexer (128-word, A/D voltage scaling)
  - AGC downlink decoder (15-bit word reassembly from DNTM1/DNTM2)

Voice and analog (Phase 3):
  - 1.25 MHz FM voice subcarrier demod to 8 kHz audio
  - SCO demodulator for 9 analog sensor channels (14.5-165 kHz)

Virtual AGC integration (Phase 4):
  - TCP bridge client with auto-reconnect and channel filtering
  - DSKY uplink encoder (VERB/NOUN/DATA command sequences)

Top-level receiver (Phase 5):
  - usb_downlink_receiver hier_block2: one block, complex in, PDUs out
  - 14 GRC block YAML definitions for GNU Radio Companion
  - Example scripts for signal analysis and full-chain demo

Infrastructure:
  - constants.py with all timing/frequency/frame parameters
  - protocol.py for sync word + AGC packet encode/decode
  - Synthetic USB signal generator for testing
  - 222 tests passing, ruff lint clean
2026-02-20 13:18:42 -07:00