Rename project from travler-rotor to birdcage
The radome looks like a birdcage, ham operators call satellites "birds", and it's a nod to saveitforparts saving dishes "for parts." Package, CLI entry point, class names (BirdcageAntenna), env vars (BIRDCAGE_PORT, etc.), and CLAUDE.md updated. Hardware references (Winegard Trav'ler, Trav'ler Pro, Carryout G2) unchanged.
This commit is contained in:
parent
c010cee282
commit
a2e807f973
9 changed files with 207 additions and 57 deletions
161
CLAUDE.md
161
CLAUDE.md
|
|
@ -4,18 +4,19 @@ Control a Winegard Trav'ler motorized satellite dish via RS-485 for amateur radi
|
|||
|
||||
## Project
|
||||
|
||||
- **Package:** `travler-rotor` (installed via `uv sync`)
|
||||
- **CLI entry point:** `travler-rotor` (init / serve / pos / move)
|
||||
- **Source layout:** `src/travler_rotor/` (src-layout)
|
||||
- **Packages:** `birdcage` + `console-probe` (installed via `uv sync`)
|
||||
- **CLI entry points:** `birdcage` (init / serve / pos / move), `console-probe` (probe / discover)
|
||||
- **Source layout:** `src/birdcage/` and `src/console_probe/` (src-layout)
|
||||
- **Original upstream:** `Trav-ler-Rotor-For-HAL-2.05/` — Gabe Emerson's scripts, kept as reference (do not modify)
|
||||
|
||||
## Build & Lint
|
||||
|
||||
```bash
|
||||
uv sync # Install deps + package
|
||||
uv sync # Install deps + both packages
|
||||
uv run ruff check src/ # Lint
|
||||
uv run ruff format --check src/ # Format check
|
||||
uv run travler-rotor --help # CLI smoke test
|
||||
uv run birdcage --help # CLI smoke test
|
||||
uv run console-probe --help # Probe tool smoke test
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
|
@ -25,13 +26,29 @@ protocol.py — FirmwareProtocol ABC + HAL205Protocol / HAL000Protocol
|
|||
Serial I/O owned here. Each firmware version is a subclass.
|
||||
leapfrog.py — Pure function: apply_leapfrog(target, current) -> adjusted
|
||||
Predictive overshoot to compensate for mechanical motor lag.
|
||||
antenna.py — TravlerAntenna: high-level control wrapping protocol + leapfrog
|
||||
antenna.py — BirdcageAntenna: high-level control wrapping protocol + leapfrog
|
||||
This is what consumers (CLI, rotctld, future MCP server) call.
|
||||
rotctld.py — RotctldServer: Hamlib rotctld TCP protocol (p/P/S/_/q)
|
||||
Bridges Gpredict to the antenna.
|
||||
cli.py — Click CLI with init/serve/pos/move subcommands
|
||||
```
|
||||
|
||||
### console-probe package
|
||||
|
||||
```
|
||||
profile.py — DeviceProfile + HelpEntry dataclasses
|
||||
serial_io.py — Prompt-aware serial I/O (fixes > termination bug)
|
||||
discovery.py — Auto-discovery, help parsing, submenu probing, candidates
|
||||
report.py — JSON report with format_version 2 (menus/help/undiscovered)
|
||||
cli.py — argparse CLI: --discover-only, --deep, --submenu, --json
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
console-probe --port /dev/ttyUSB2 --baud 115200 --discover-only --json /tmp/d.json
|
||||
console-probe --port /dev/ttyUSB2 --baud 115200 --deep --wordlist scripts/wordlists/winegard.txt
|
||||
```
|
||||
|
||||
## Firmware Variants
|
||||
|
||||
Five known Winegard dish variants documented by Gabe Emerson (KL1FI) / saveitforparts and cdavidson0522:
|
||||
|
|
@ -455,6 +472,138 @@ v — go to velocity (continuous spin): `v [motor] [ustep/sec]`
|
|||
? / q — help / return to TRK>
|
||||
```
|
||||
|
||||
### K60 GPIO Functional Pin Map (Carryout G2)
|
||||
|
||||
Cross-referenced from live `gpio dir`/`gpio regs` queries (2026-02-13), K60 datasheet
|
||||
pin mux table (MK60DN512VLQ10, 144-LQFP), boot log peripheral init, and A3981 datasheet.
|
||||
|
||||
**SPI1 — A3981 Stepper Motor Drivers (4 MHz, mode 0x03)**
|
||||
|
||||
| K60 Pin | GPIO | Alt | Function | Dir | State | Notes |
|
||||
|---------|------|-----|----------|-----|-------|-------|
|
||||
| PTE0 | E0 | ALT2 | SPI1_PCS1 | OUT | 1 | A3981 #2 chip select (EL motor) |
|
||||
| PTE1 | E1 | ALT2 | SPI1_SOUT | (periph) | 1 | MOSI — MCU to A3981 |
|
||||
| PTE2 | E2 | ALT2 | SPI1_SCK | (periph) | 1 | SPI clock |
|
||||
| PTE3 | E3 | ALT2 | SPI1_SIN | (periph) | 0 | MISO — A3981 to MCU |
|
||||
| PTE4 | E4 | ALT2 | SPI1_PCS0 | IN* | 1 | A3981 #1 chip select (AZ motor) |
|
||||
| PTE5 | E5 | ALT2 | SPI1_PCS2 | OUT | 1 | Possibly A3981 RESET or enable |
|
||||
|
||||
*PTE4 shows INPUT in GPIO dir register, but this is irrelevant when muxed to SPI peripheral.
|
||||
The SPI controller manages chip select assertion/deassertion directly.
|
||||
|
||||
**SPI2 — BCM4515 DVB-S2 Tuner (6.857 MHz, mode 0x03)**
|
||||
|
||||
| K60 Pin | GPIO | Alt | Function | Dir | State | Notes |
|
||||
|---------|------|-----|----------|-----|-------|-------|
|
||||
| PTD11 | D11 | ALT2 | SPI2_PCS0 | OUT | 1 | BCM4515 chip select |
|
||||
| PTD12 | D12 | ALT2 | SPI2_SCK | IN* | 1 | SPI clock |
|
||||
| PTD13 | D13 | ALT2 | SPI2_SOUT | IN* | 1 | MOSI — MCU to BCM4515 |
|
||||
| PTD14 | D14 | ALT2 | SPI2_SIN | — | 0 | MISO — BCM4515 to MCU |
|
||||
| PTD15 | D15 | ALT2 | SPI2_PCS1 | — | 0 | Secondary chip select (unused?) |
|
||||
|
||||
*GPIO dir register not meaningful for peripheral-muxed pins.
|
||||
|
||||
**UART4 — RS-422 Console (115200 baud)**
|
||||
|
||||
| K60 Pin | GPIO | Alt | Function | Dir | State | Notes |
|
||||
|---------|------|-----|----------|-----|-------|-------|
|
||||
| PTE24 | E24 | ALT3 | UART4_TX | OUT | 1 | Console TX (to computer RX pair) |
|
||||
| PTE25 | E25 | ALT3 | UART4_RX | IN | 1 | Console RX (from computer TX pair) |
|
||||
| PTE26 | E26 | ALT3 | UART4_CTS | IN | 1 | Hardware flow control (idle high) |
|
||||
| PTE27 | E27 | — | GPIO | IN | 1 | Unknown (RTS? or pullup) |
|
||||
| PTE28 | E28 | — | GPIO | IN | 1 | Unknown |
|
||||
|
||||
**DIP Switch GPIOs**
|
||||
|
||||
`dipswitch` reads raw value `val:ffffff01` (all OFF/up) → `app_dipswitch:101` (DISH 110+119+129W).
|
||||
Exact GPIO pins TBD — likely Port A or Port C inputs with internal pullups. The 0xffffff01
|
||||
raw value suggests a 32-bit register read where bits 1-24 are all high (pullup, switches open)
|
||||
and bit 0 is high (LSB).
|
||||
|
||||
**A3981 Diagnostic Pins**
|
||||
|
||||
The `a3981 diag` command reads fault status from two GPIO pins (one per motor driver).
|
||||
Confirmed both read "OK" when motors are healthy. The A3981 DIAG output is active-low
|
||||
open-drain, pulled high when no fault. Exact GPIO pins TBD.
|
||||
|
||||
**Unidentified High-State Outputs**
|
||||
|
||||
| GPIO | Dir | State | Likely Function |
|
||||
|------|-----|-------|-----------------|
|
||||
| D10 | OUT | 1 | BCM4515 reset or power enable |
|
||||
| B0-B3 | — | 1 | SPI0 or I2C bus (B0-B3 cluster) |
|
||||
| B11 | — | 1 | Status LED or peripheral enable |
|
||||
| C10-C13 | — | 1 | Contiguous block — possibly bus interface |
|
||||
| C18 | — | 1 | LNB voltage control or relay |
|
||||
|
||||
### azscanwxp — Radio Telescope Mode (Carryout G2)
|
||||
|
||||
The `azscanwxp` command in MOT> performs an azimuth sweep while cycling through
|
||||
DVB transponders at each position. This is the core of Davidson's winegard-sky-scan
|
||||
project for RF imaging of the sky.
|
||||
|
||||
**Usage:** `azscanwxp [motor] [span] [resolution] [num_xponders]`
|
||||
|
||||
| Parameter | Type | Units | Description |
|
||||
|-----------|------|-------|-------------|
|
||||
| motor | int | — | Motor ID (0=AZ, 1=EL) |
|
||||
| span | float | degrees | Total azimuth sweep range |
|
||||
| resolution | int | centidegrees (0.01 deg) | Step size per position |
|
||||
| num_xponders | int | — | Number of transponders to cycle at each position |
|
||||
|
||||
**Example:** `azscanwxp 0 10 100 3` — sweep 10 degrees on AZ at 1.00 degree steps,
|
||||
checking 3 transponders per position.
|
||||
|
||||
**Output format** (from ADC `scan` documentation):
|
||||
```
|
||||
Motor:<id> Angle:<cdeg> RSSI:<adc> Lock:<0/1> SNR:<dB> Scan Delta:<step>
|
||||
```
|
||||
|
||||
**Safety:** Requires homed motors. Do NOT run on uncalibrated axes — the firmware
|
||||
may target INT_MAX (2147483647 steps) and deadlock the shell.
|
||||
|
||||
**For ham radio sky mapping:** Set the DVB tuner to a frequency near your target
|
||||
(e.g., 10 GHz Ku-band downconverted through the LNB to ~1178 MHz IF), enable LNA
|
||||
with `dvb` → `lnbdc odu`, then run azscanwxp. The RSSI values map RF power at
|
||||
each AZ/EL grid point. Post-process the output into a 2D heatmap for sky imaging.
|
||||
|
||||
### DiSEqC 2.x Interface (Carryout G2)
|
||||
|
||||
The BCM4515 provides a DiSEqC 2.x controller accessible from the DVB> submenu.
|
||||
DiSEqC (Digital Satellite Equipment Control) uses 22 kHz tone bursts on the coax
|
||||
LNB bias line to control switches, LNB polarity, and band selection.
|
||||
|
||||
**Timing Parameters (confirmed live 2026-02-13):**
|
||||
|
||||
| Command | Value | Description |
|
||||
|---------|-------|-------------|
|
||||
| `ovraddr` | 0x11 | Target LNB address (standard first LNB) |
|
||||
| `rrto` | 210 ms | Receive reply timeout |
|
||||
| `pretx` | 15 ms | Pre-command TX delay |
|
||||
| `tdthresh` | 110 | Tone detect threshold (0.16 counts/mV) |
|
||||
|
||||
**DiSEqC Commands:**
|
||||
|
||||
| Command | Function | Status |
|
||||
|---------|----------|--------|
|
||||
| `di2conf` | Read LNB config register | RxReplyTimeout (no switch connected) |
|
||||
| `di2id` | Read LNB hardware ID | RxReplyTimeout |
|
||||
| `di2stat` | Read LNB status flags | RxReplyTimeout |
|
||||
| `di2rcs` | Read committed switch status | RxReplyTimeout |
|
||||
| `di2cs` | Configure committed switch | Needs parameters |
|
||||
| `di2sc` | Short circuit test | Untested |
|
||||
| `send <hex>` | Raw DiSEqC packet (max 6 bytes) | Functional |
|
||||
|
||||
**Raw DiSEqC packets:** The `send` command accepts space-delimited hex bytes.
|
||||
Standard DiSEqC 1.x commands use the format: `send E0 10 38 Fx` where the
|
||||
last byte selects the switch port (F0-F3 for ports 1-4).
|
||||
|
||||
**For ham radio:** DiSEqC can control LNB polarity (13V=V-pol, 18V=H-pol) and
|
||||
22 kHz tone (band select) without rewiring. The `lnbdc odu` command sets 13V;
|
||||
boot default is 18V. Polarity affects which transponders are visible and RSSI
|
||||
readings from `rssits` in the PEAK> submenu, which alternates between even
|
||||
(H-pol/18V) and odd (V-pol/13V) transponders.
|
||||
|
||||
### Known NVS Indices
|
||||
|
||||
Full dump in `docs/g2-nvs-dump.md` (firmware 02.02.48, captured 2026-02-12).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue