HMC472ASerial class implements usb-serial-json-v1 protocol over the
ESP32-S3's native USB CDC port. Auto-detection scans /dev/ttyACM* and
probes with the identify command to find the right port.
--attenuator flag now defaults to 'auto' (USB first, HTTP fallback).
Also accepts direct serial port paths or HTTP URLs for explicit control.
New tool (tools/rf_testbench.py) automates five test sequences using a
NanoVNA as a CW source and HMC472A digital attenuator (0-31.5 dB, 0.5 dB
steps via REST API) to characterize the SkyWalker-1 receiver:
- AGC linearity mapping across 64 attenuation steps
- IF band flatness sweep (950-1500 MHz)
- Frequency accuracy via peak detection
- Minimum detectable signal search
- BPSK mode 9 CW probe (Viterbi rate 1/2 K=7)
Includes SKYWALKER_MOCK=1 mode, path-loss calibration from NanoVNA S21
sweeps, and safe-state cleanup (attenuator to max on exit, LNB power
never enabled in direct-input mode).
Also adds Applications & Use Cases guide, RF Test Bench docs page, fixes
h21cm cable loss (was 3x too high), and updates sidebar.
Four new tools transforming the SkyWalker-1 from satellite TV receiver into
a general-purpose RF observatory:
- skywalker-mcp: FastMCP server exposing 20 tools, 4 resources, 2 prompts.
Thread-safe DeviceBridge with motor safety (continuous drive opt-in),
input validation on all frequency/symbol rate/step parameters,
try/finally on TS capture, path traversal sanitization, and reduced
lock scope so emergency motor halt isn't blocked during long surveys.
- h21cm.py: Hydrogen 21 cm drift-scan radiometer at 1420.405 MHz with
Doppler velocity calculation, control band comparison, and CSV output.
- beacon_logger.py: Long-term Ku-band beacon SNR/AGC logger with auto-relock,
dual CSV/JSONL output, signal handlers, and systemd unit generation.
- arc_survey.py: Multi-satellite orbital arc census with USALS motor control,
per-slot catalog persistence, resume support, and defensive motor halt
on all error/interrupt paths.
Documentation: experimenter's roadmap guide + 4 tool reference pages (48 pages total).
Phase D firmware hardening: vendor commands 0xBD (streaming diagnostics)
and 0xBE (I2C hot-plug detection) with Python library, bridge, and demo
support. All I2C operations use timeout-protected helpers, BCM4500 reads
are rate-limited during streaming, and frame counter reads use atomic
read-verify-reread pattern. Counters saturate instead of wrapping.
Firmware v3.02.0 adds three new vendor commands:
- 0xB7 SIGNAL_MONITOR: fast 8-byte combined signal read
- 0xB8 TUNE_MONITOR: tune + dwell + read in one round-trip
- 0xB9 MULTI_REG_READ: batch read up to 64 indirect registers
New tools/skywalker.py provides five modes that use the BCM4500's
AGC registers as a crude power detector across 950-2150 MHz IF,
even without demodulator lock:
- spectrum: sweep analyzer with ASCII/waterfall/matplotlib display
- scan: automated transponder scanner (sweep + peak detect + blind scan)
- monitor: real-time signal strength for dish alignment
- lband: direct input analyzer with L-band allocation annotations
- track: carrier/beacon tracker with CSV/JSON logging and drift detection
Extracts shared SkyWalker1 class and constants into skywalker_lib.py;
tune.py now imports from the shared library.
Removed I2CS bmSTOP "bus reset" from bcm4500_boot() and debug modes.
Sending STOP with no active transaction puts the FX2 I2C controller
into an inconsistent state where subsequent START+ACK detection fails.
Root cause identified through incremental debug modes (wValue 0x80-0x85)
on live hardware: mode 0x82 (with bmSTOP) fails, mode 0x85 (identical
but without bmSTOP) succeeds. Raw I2C reads confirm BCM4500 is alive
the entire time -- only the controller state is corrupted.
BCM4500 now boots successfully in ~90ms. Three I2C devices found on
bus: 0x08 (BCM4500), 0x10 (tuner/LNB), 0x51 (EEPROM).
Also in this commit:
- Timeout-protected I2C functions replacing fx2lib bare while loops
- I2C bus scan and debug mode infrastructure
- Kernel driver blacklist for dvb_usb_gp8psk
- Test tools for incremental boot debugging
- Technical findings documented in docs/boot-debug-findings.md
Custom firmware (SDCC + fx2lib) implements all stock vendor commands
(0x80-0x94) plus new commands for spectrum sweep (0xB0), raw BCM4500
register access (0xB1/0xB2), and blind scan (0xB3). Compiles to 6.3KB
of code with healthy RAM margins.
RAM loader (fw_load.py) uses the FX2 0xA0 vendor request to load
firmware into RAM without touching EEPROM -- power cycle restores
factory firmware. Supports Intel HEX and raw binary formats.
New tools:
- tools/eeprom_write.py: EEPROM firmware flash with backup, verify, dry-run
- tools/ts_analyze.py: MPEG-2 transport stream analyzer with PAT/PMT parsing
DVB-S2 investigation confirms BCM4500 hardware limitation (no LDPC/BCH silicon).
Fix --json flag on tune.py subcommands (argparse parent/child scoping).
All tools verified against live SkyWalker-1 hardware.
Python tool (tools/tune.py) implements all vendor USB control
commands for tuning, LNB control, DiSEqC switching, and MPEG-2
transport stream capture via pyusb. Includes CLI subcommands for
status, tune, stream, diseqc, and lnb operations.
Consolidated hardware reference merges all Phase 1 analysis into
a single 12-section document covering the complete USB interface,
all 30 vendor commands, BCM4500 demodulator protocol, GPIF
streaming path, DiSEqC timing, and cross-version firmware
comparison.
Updater EXEs are packed (RWX sections, near-random entropy) with anti-debug
protection (IsDebuggerPresent/SoftICE check). Bypassed by running under plain
Wine and reading /proc/PID/mem with elevated privileges.
SW1 v2.13.x updater contains 3 firmware variants (likely .1/.2/.3):
- All use LJMP 0x170D entry, 9322-9377 bytes, 10 C2 records each
- FW2 vs FW3 differ by 1525 bytes (most similar pair)
Rev.2 v2.10.4 updater contains 1 firmware image:
- PID=0x0202 (vs SW1's 0x0203), LJMP 0x155F, 8843 bytes, 9 C2 records
All images use standard Cypress C2 EEPROM format with entry at 0xE600 (CPUCS).
Previous RAM dumps via 0xA0 vendor request turned out to be live FIFO
data, not firmware - the Genpix FX2 firmware overrides the standard
0xA0 handler. Discovered that I2C_READ (0x84) with wValue=0x51 and
wIndex=offset reads the boot EEPROM directly.
EEPROM contents (Cypress C2 format):
- VID:PID 09C0:0203, config 0x40 (400kHz I2C)
- 9,472 bytes of 8051 firmware in 10 load records
- Code range 0x0000-0x24FF, entry at LJMP 0x188D
- Ghidra auto-analysis finds 61 functions
Tools: eeprom_dump.py (full dump), eeprom_probe.py (I2C protocol discovery)
Dumped 8KB internal RAM and 64KB external RAM from SkyWalker-1
serial #00857 via Cypress FX2 vendor request 0xA0. Device reports
FW v2.06.4 (build 2007-07-13). Tool also scans all vendor USB
commands and probes device status registers.