gr-apollo/CLAUDE.md

201 lines
7.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CLAUDE.md
This file provides guidance to Claude Code when working with gr-apollo.
## Project Overview
GNU Radio 3.10+ out-of-tree (OOT) module for decoding **Apollo Unified S-Band (USB)** telecommunications signals. Based on the 1965 NAA Telecommunication Systems Study Guide (Course A-624) and Virtual AGC project.
**Target signals:**
- Downlink: 2287.5 MHz (spacecraft → ground)
- Uplink: 2106.40625 MHz (ground → spacecraft)
- Coherent ratio: 240/221 (Tx = Rx × 240/221)
## Repository Structure
```
gr-apollo/
├── src/apollo/ # GNU Radio Python blocks (src-layout)
│ ├── pm_demod.py # PM demodulator (0.133 rad peak)
│ ├── bpsk_subcarrier_demod.py # 1.024 MHz BPSK subcarrier
│ ├── pcm_frame_sync.py # 32-bit sync, 128-word frames
│ ├── pcm_demux.py # Frame demultiplexer
│ └── voice_subcarrier_demod.py # 1.25 MHz FM voice
├── grc/ # GRC block YAML definitions
├── docs/ # Reference documentation
├── examples/ # Example flowgraphs
├── pyproject.toml # Python package configuration
└── README.md
```
## Development Commands
```bash
# Install in development mode
uv pip install -e .
# Install GRC block definitions
cp grc/*.yml ~/.local/share/gnuradio/grc/blocks/
# Test with gr-mcp (if available)
# Use protocol analysis tools to generate decoder chain
```
## Signal Architecture
### Downlink Signal Chain (2287.5 MHz)
```
RF Input → Carrier PLL → PM Demod → Subcarrier Separation
┌───────────────────────┼───────────────────────┐
↓ ↓ ↓
1.024 MHz BPSK 1.25 MHz FM Ranging
(PCM telemetry) (Voice) (PRN code)
↓ ↓
Symbol Sync FM Discriminator
↓ ↓
51.2 kbps NRZ 300-3000 Hz audio
Frame Sync (32-bit)
128-word demux
```
### Key Parameters
| Parameter | Value | Notes |
|-----------|-------|-------|
| Downlink frequency | 2287.5 MHz | Coherent with uplink |
| PM peak deviation | 0.133 rad (7.6°) | Phase modulation |
| PCM subcarrier | 1.024 MHz | BPSK modulated |
| PCM bit rate | 51.2 kbps (high) / 1.6 kbps (low) | NRZ, MSB first |
| Voice subcarrier | 1.25 MHz | FM, ±29 kHz deviation |
| Frame length | 128 words × 8 bits | 50 fps high rate |
| Frame sync | 32-bit pattern | Complements on odd frames |
| Master clock | 512 kHz | All timing derived from this |
### PCM Frame Structure
```
┌─────────────────────────────────────────────────────────────┐
│ Frame Sync (32 bits = 4 words) │
│ [5-bit A][15-bit core][6-bit B][6-bit frame ID] │
├─────────────────────────────────────────────────────────────┤
│ Data Words 5-128 (124 words) │
│ - High-level analog (0-5V, 8-bit) │
│ - Low-level analog (0-40mV, 8-bit with ×125 gain) │
│ - Digital parallel/serial inputs │
│ - AGC downlink data (channels 34, 35, 57) │
└─────────────────────────────────────────────────────────────┘
50 frames = 1 subframe (1 second at high rate)
```
### Subcarrier Oscillators (FM Mode)
| SCO | Center Freq | Deviation | Use |
|-----|-------------|-----------|-----|
| 1 | 14,500 Hz | ±7.5% | Analog sensor |
| 2 | 22,000 Hz | ±7.5% | Analog sensor |
| 3 | 30,000 Hz | ±7.5% | Analog sensor |
| 4 | 40,000 Hz | ±7.5% | Analog sensor |
| 5 | 52,500 Hz | ±7.5% | Analog sensor |
| 6 | 70,000 Hz | ±7.5% | Analog sensor |
| 7 | 95,000 Hz | ±7.5% | Analog sensor |
| 8 | 125,000 Hz | ±7.5% | Analog sensor |
| 9 | 165,000 Hz | ±7.5% | Analog sensor |
## GNU Radio Blocks to Implement
### Phase 1: Core Demodulation
| Block | Type | I/O | Description |
|-------|------|-----|-------------|
| `pm_demod` | `gr.sync_block` | complex→float | PM demodulator with carrier recovery |
| `subcarrier_extract` | `gr.sync_block` | float→complex | Bandpass + downconvert subcarrier |
| `bpsk_demod` | `gr.sync_block` | complex→byte | BPSK demodulation with symbol sync |
### Phase 2: PCM Processing
| Block | Type | I/O | Description |
|-------|------|-----|-------------|
| `pcm_frame_sync` | `gr.basic_block` | byte→PDU | 32-bit sync detection, frame extraction |
| `pcm_demux` | `gr.basic_block` | PDU→PDU | Demultiplex 128-word frames by word position |
| `downlink_decoder` | `gr.basic_block` | PDU→dict | Interpret AGC telemetry lists |
### Phase 3: Voice & Analog
| Block | Type | I/O | Description |
|-------|------|-----|-------------|
| `fm_voice_demod` | `gr.sync_block` | complex→float | 1.25 MHz FM subcarrier → audio |
| `sco_demod` | `gr.sync_block` | float→float | FM SCO demodulator (configurable) |
## Virtual AGC Integration
The Virtual AGC emulator communicates via TCP socket (port 19697+):
```
4-byte packet format:
Byte 0: [Channel bits 8-4][0x00]
Byte 1: [0x40 | Channel bits 3-1][Value bits 14-12]
Byte 2: [0x80 | Value bits 11-6]
Byte 3: [0xC0 | Value bits 5-0]
```
Key telecom channels:
- **Ch 45 (INLINK)**: Uplink data input
- **Ch 57 (OUTLINK)**: Downlink data output
- **Ch 34/35 (DNTM1/2)**: Telemetry word stream
## References
- [Implementation Spec](../virtualagc/telecom_study_guide/IMPLEMENTATION_SPEC.md)
- [Virtual AGC Project](https://www.ibiblio.org/apollo/)
- [NASA Apollo USB Description](https://ntrs.nasa.gov/)
- [NAA Course A-624 Study Guide](https://archive.org/details/apollo-telecommunications)
## Code Style
- Python: Follow GNU Radio block patterns (numpy for DSP)
- Use gr-mcp protocol analysis tools for decoder chain generation
- Test blocks in Docker before integration
## Docs Site Deployment
Starlight documentation site in `docs/` subdirectory.
- **Production**: https://gr-apollo.warehack.ing
- **Local dev**: Set `DOMAIN=gr-apollo.l.warehack.ing` in `docs/.env`
- **Git**: `git@git.supported.systems:warehack.ing/gr-apollo.git`
- **Server**: `ssh -A warehack-ing@warehack.ing`, repo at `~/gr-apollo`
### Environment
Copy `.env.example` to `.env` and set:
```env
COMPOSE_PROJECT=gr-apollo-docs
DOMAIN=gr-apollo.warehack.ing
```
### Commands
```bash
# From docs/ directory:
make up # Production — Caddy serves static dist/
make dev # Development — Astro dev server with HMR
make down # Stop all containers
make logs # Tail container logs
```
### Deploy to Production
```bash
# One-liner from local machine
ssh -A warehack-ing@warehack.ing "cd ~/gr-apollo && git pull && cd docs && make up"
```
### Notes
- Uses Docker Compose profiles (`prod` / `dev`)
- Playwright + Chromium installed in build stage for mermaid diagram rendering
- caddy-docker-proxy on external `caddy` network handles TLS automatically