37 Commits

Author SHA1 Message Date
aecad367a0 Fix remaining safety review findings: DiSEqC timeout, hotplug, watchdog status
Addresses all remaining Apollo review items:

- C-3: DiSEqC Timer2 spin loops now have timeout protection via
  diseqc_wait_ticks() with per-tick I2C_TIMEOUT countdown. Tone burst
  refactored to use the shared helper instead of bare while(!TF2) loops.
  New ERR_DISEQC_TIMER (0x0C) error code on Timer2 failure.

- I-3: Hotplug scan hp_prev copy moved from start to end of scan.
  Aborted scans no longer corrupt the previous-good baseline, preventing
  false "removed" events on consecutive scan failures.

- S-1: Watchdog-fired detection in main loop — when wdt_armed==2 (ISR
  fired), sets ERR_WDT_FIRED (0x0D) readable via 0xBC and clears
  BM_STARTED|BM_FW_LOADED|BM_ARMED so host sees system is down.

- I-2: Comment explaining (WORD)sd_poll_count cast as SDCC optimization.

- I-1: CKCON bit ownership comment in diseqc_tone_burst() Timer2 setup.

Code: 13,079 / 15,360 bytes (85%). XRAM: 218 / 512. Stack: 132 bytes.
2026-02-16 05:48:43 -07:00
834c2bd9ee Add software watchdog and timeout protection for all I2C/USB paths (firmware v3.05.0)
Safety review identified infinite-hang paths in do_tune(), GPIF streaming,
EP0/EP2 FIFO waits, and the 0xB4 I2C bus scan. The firmware controls an LNB
power supply (750mA at 18V) on a Cypress FX2LP with no hardware watchdog.

Key changes:
- Software watchdog via Timer0 ISR (~2s timeout, cuts LNB power on stall)
- Replace fx2lib i2c_write() in do_tune() with timeout-protected helper
- ep0_wait_data() helper replaces 7 bare EP0 BUSY spin loops
- GPIF idle wait and EP2 FIFO full wait now have timeouts
- 0xB4 I2C bus scan uses i2c_wait_done()/i2c_wait_stop() instead of bare spins
- Return-value checks on all I2C writes in sweep/scan functions
- EP0 payload length validation on all vendor commands with data phase
- Zero-fill EP0BUF before indirect reads (0x87, 0xB7) for deterministic output
- i2c_wait_stop() now sets last_error on timeout
- New error codes: ERR_TUNE_FAIL through ERR_DISEQC_LEN
- BCM_LOCK_BIT constant replaces hardcoded 0x20 in lock checks
- DiSEqC Tone Burst B rejected with ERR_NOT_SUPPORTED
- DiSEqC message length error sets ERR_DISEQC_LEN
- hp_changes counter saturates instead of wrapping
- stream_diag_poll() only updates status on successful I2C reads
- do_tune() forward declaration eliminates implicit-function warning
- do_tune() sets ERR_BCM_NOT_READY when demod not booted
- wdt_kick() in all long-running sweep/scan loops

Code: 13,057 / 15,360 bytes (85%). XRAM: 218 / 512 bytes (43%).
Stack: 132 bytes free. Zero new SDCC warnings.
2026-02-16 03:41:08 -07:00
6e353c351f Add I2C hot-plug detection and streaming diagnostics (firmware v3.04.0)
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.
2026-02-15 18:24:45 -07:00
592898dd7a Add F9/F10 screenshots, fix duplicate widget ID in motor screen
Generate motor.svg and survey.svg for the new TUI screens. Fix
MotorScreen bug: two Horizontal widgets shared id="motor-usals-inputs",
causing MountError. Replaced with classes="usals-input-row" since both
rows need the same styling. Regenerated all 13 screenshots.
2026-02-15 18:05:15 -07:00
cc3a0707a1 Add DiSEqC motor control, QO-100 DATV reception, and carrier survey
Firmware v3.03.0: DiSEqC Manchester encoder (cmd 0x8D extended),
parameterized spectrum sweep (0xBA), adaptive blind scan (0xBB),
error code reporting (0xBC). All new function locals moved to XDATA
to fit within FX2LP 256-byte internal RAM constraint.

Motor control: DiSEqC 1.2 positioner with USALS GotoX, stored
positions, interactive keyboard jog, 30-second safety auto-halt.

QO-100 DATV: Es'hail-2 wideband transponder tools — LNB IF
calculator, narrowband scan, tune, and TS-to-video pipe (ffplay/mpv).

Carrier survey: six-stage pipeline (coarse sweep → peak detection →
fine sweep → blind scan → TS sample → catalog). JSON catalog with
differential analysis, QO-100 optimized mode, CSV/text export.

TUI: F9 Motor screen (3-column layout with signal gauge), F10 Survey
screen (Full Band + QO-100 tabs). Bridge, demo, and theme updated.

Docs: motor.mdx, survey.mdx, qo100-datv.mdx guide, tui.mdx updated
for 10 screens. Site builds 41 pages, all links valid.
2026-02-15 17:01:11 -07:00
0f4ba4766f Add TUI documentation for F6-F8 screens and regenerate screenshots
Update tui.mdx with Device, Stream, and Config screen sections
including keyboard shortcuts, Tabs/Steps components, and safety
warnings. Update generate_screenshots.py to capture all 11 screens.
Regenerate all SVGs with current sidebar layout.
2026-02-14 16:24:59 -07:00
567bf4d9e0 Add Device, Stream, and Config screens to TUI (F6-F8)
Expand from 5 to 8 mode screens. F6 Device provides firmware
management, EEPROM flash with full safety state machine (C2
validation, auto-backup, 3s countdown, page write, byte verify),
and diagnostics (boot test, I2C scan, register dump). F7 Stream
does live TS capture with PID distribution and PAT/PMT tree.
F8 Config manages LNB power, DiSEqC switching, and modulation/FEC.

Foundation: 12 new SkyWalker1 methods (device info, FX2 RAM,
EEPROM I2C, diagnostics), matching DemoDevice synthetics with
realistic C2 image and TS packets, 20 bridge wrappers (RLock).
2026-02-14 16:08:58 -07:00
5d9dfa7794 Add TUI documentation page with generated SVG screenshots
- New docs page (tools/tui.mdx) covering all 5 RF modes, keyboard
  shortcuts, easter eggs, and splash screen with inline SVG screenshots
- Screenshot generation script using Textual headless Pilot API to
  capture 8 screens in demo mode without hardware
- Fix dark mode toggle: migrate from removed App.dark to App.theme API
  (Textual 7.x breaking change)
- Update social link to Gitea repo, add TUI to sidebar
2026-02-14 14:49:02 -07:00
6dcb6b693a Add radar scope, splash screen, Star Wars easter egg, and harden TUI
New features:
- P1 green phosphor radar scope widget on Track screen with LUT-optimized rendering
- Splash screen with pre-baked ANSI half-block art from 16colo.rs/Mistigris
- Star Wars ASCII animation via telnet (ctrl+w) with IPv6 happy eyeballs and offline fallback
- Dark Side / New Hope toast notifications on theme toggle
- Kitty terminal detection with cat emoji on splash

Robustness (from Apollo code review):
- Circuit breaker in track loop after 10 consecutive errors
- Input validation for frequency, symbol rate, step size across scan/spectrum/track
- Consolidated sys.path manipulation into __init__.py
- Radar scope pre-computes dist/angle LUT per pixel on resize

Cleanup:
- Removed unused imports across lband, monitor, scan, signal_gauge
- Moved Pillow/textual-image to optional dev deps (splash uses pre-baked ANSI)
- Added 41-test pytest suite covering telnet IAC parsing, radar geometry, splash assets
2026-02-14 09:51:58 -07:00
8da486719a Fix mode panels: Screen → Container with on_show/on_hide lifecycle
Textual's ContentSwitcher expects regular Widget/Container children,
not Screen subclasses. Screen's on_mount fires for all children at
once regardless of visibility, so demo workers for all 5 modes
started simultaneously and competed for the bridge.

Container children get proper on_show/on_hide from ContentSwitcher's
visibility toggling — only the active panel's worker runs.
2026-02-13 04:42:59 -07:00
64c33985a3 Add Textual TUI for SkyWalker-1 RF tool
Separate entry point (skywalker-tui) that reuses skywalker_lib.py
unchanged. Five RF modes: spectrum, scan, monitor, lband, track —
each with threaded USB bridge workers for non-blocking I/O.

Includes --demo mode with synthetic signal generation (Gaussian
peaks, noise floor, AGC simulation) for development without hardware.

Custom widgets: spectrum bar chart, rolling waterfall, signal gauge,
sparkline history, transponder table, device status bar.
2026-02-13 04:39:55 -07:00
c4bfe33d61 Replace monolithic Master Reference with focused Sources page
The 1711-line master reference was 100% duplicated across the existing
37 Starlight pages. Trimmed to bibliography only (Ghidra port numbers,
driver source paths, analysis reports, community links).

Salvaged FX2 USB controller registers (SETUPDAT, CPUCS, EP0BUF, etc.)
into bcm4500/register-map.mdx before removal. Sidebar label updated
from "Master Reference" to "Sources".
2026-02-13 02:52:49 -07:00
7b27c93219 Reorder firmware versions: custom first, then newest-to-oldest stock 2026-02-13 02:46:54 -07:00
2bf6515cbb Add deployment instructions and site links to CLAUDE.md 2026-02-13 01:51:00 -07:00
7cded611e4 Add project README with hardware overview and tool reference 2026-02-12 23:35:28 -07:00
a7daecded6 Add Docker deployment config and v3.02 firmware docs
Deployment: Dockerfile (multi-stage dev/prod with Caddy static
serving), docker-compose.yml (caddy-docker-proxy labels),
Caddyfile, Makefile, .dockerignore.

Docs: v3.02 firmware page, v3.01 updates.
2026-02-12 23:31:55 -07:00
867b304773 Add BCM4500 register map and fill documentation gaps
New page: bcm4500/register-map.mdx consolidates all register
addresses (direct, indirect page 0, FX2 XRAM/IRAM, I2C controller)
into a single lookup reference with cross-reference index.

Expanded sections:
- fw213-variants: hardware detection mechanism, distinguishing
  characteristics table, FW1 demod type detection signatures
- demodulator: probe logic (3x3 retry, INT0 40-iteration boot probe
  at 0x7F/0x3F, no_demod_flag graceful degradation)
- version-comparison: version ID gap aside (v2.07.04 is a kernel
  constant, not a real firmware release)

Cross-links added to signal-monitoring and tuning-protocol pages.
2026-02-12 23:28:54 -07:00
3f970967c4 Add Starlight docs for v3.02 signal monitoring and RF analysis tools
New pages (Diátaxis framework):
- tools/skywalker.mdx: reference for all 5 skywalker.py modes
- tools/spectrum-analysis.mdx: how-to guide for RF analysis workflows
- hardware/rf-coverage.mdx: explanation of LNB shifting and L-band coverage

Updated pages:
- firmware/custom-v301.mdx: v3.02 commands (0xB7-0xB9) with protocol docs
- usb/vendor-commands.mdx: signal monitoring command reference
- astro.config.mjs: sidebar entries and firmware version label
2026-02-12 17:38:48 -07:00
23055f34ab Add alternative operating modes: spectrum, scan, monitor, lband, track
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.
2026-02-12 17:29:00 -07:00
b21f4957f6 Add Starlight documentation site (32 pages, 9 sidebar groups)
Astro 5 + Starlight 0.37 site at site/ with teal/steel theme.
Content sourced from 14 reverse engineering docs, master reference,
and custom firmware source. Includes Tabs, Badge, Steps, Aside,
FileTree, and CardGrid components throughout. DiSEqC SVGs with
click-to-zoom via starlight-image-zoom. All internal links validated.
Pagefind search indexes all 32 pages.
2026-02-12 16:32:12 -07:00
f1d4f4f010 Add consolidated master hardware/firmware reference
Merges 11 separate analysis documents into a single 1700-line
authoritative reference covering hardware, USB, vendor commands,
BCM4500 demodulator, tuning protocol, GPIF streaming, LNB/DiSEqC,
GPIO map, firmware versions, I2C bus architecture, and all known
quirks/errata. Corrects BCM4500 I2C address to 0x08 (7-bit)
throughout.
2026-02-12 11:55:01 -07:00
d9f51548e0 Fix BCM4500 boot: spurious I2C STOP corrupted FX2 controller
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
2026-02-12 10:34:15 -07:00
890a38bfa0 Fix BCM4500 I2C address and add hardware diagnostic commands
Correct BCM4500 I2C address from 0x10 (8-bit wire) to 0x08 (7-bit)
since fx2lib shifts internally. Add i2c_combined_read() with repeated
START for proper BCM4500 register access. Add I2C bus scan (0xB4),
raw read (0xB5), and indirect protocol diagnostic (0xB6) commands.
Single-transaction indirect reads/writes for BCM4500 register protocol.

Verified on hardware: BCM4500 ACKs at 0x08, BOOT_8PSK returns config
0x03. Register reads still return zeros — BCM4500 needs DSP firmware
loaded via LOAD_BCM4500 (0x88) before registers become functional.
2026-02-12 07:17:47 -07:00
5710584267 Add custom FX2 firmware and RAM loader for open-source development
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.
2026-02-11 19:46:50 -07:00
c7b5932cc0 Add EEPROM flash tool, TS analyzer, DVB-S2 investigation, and tune.py bugfix
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.
2026-02-11 14:46:20 -07:00
a2845c37fb Add SkyWalker-1 tuning tool and consolidated hardware reference
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.
2026-02-11 12:30:05 -07:00
76f0439576 Add vendor command decode and tuning protocol deep analysis
Complete reverse engineering of all unknown vendor commands (0x8F,
0x91-0x98) across v2.06, v2.13, and Rev.2 firmware versions. Full
TUNE_8PSK (cmd 0x86) protocol analysis including EP0BUF format,
modulation dispatch jump table, BCM4500 I2C indirect register
sequences, and FEC lookup tables.
2026-02-11 12:22:01 -07:00
e4117421a1 Add GPIF streaming path and kernel firmware format analyses
GPIF streaming analysis (772 lines):
- IFCONFIG=0xEE: GPIF master mode, 48MHz async, BCM4500 data bus
- Fully hardware-managed path: BCM4500 -> GPIF -> EP2 FIFO -> USB bulk
- EP2FIFOCFG=0x0C (AUTOIN, 8-bit), FLOWSTATEA |= 0x09 (auto re-trigger)
- Byte-for-byte identical register config across all firmware versions
- ARM_TRANSFER (cmd 0x85) start/stop flow documented with disassembly

Kernel FW01 analysis (425 lines):
- FW01/FW02 files never existed in linux-firmware or any distribution
- SkyWalker-1 boots from onboard EEPROM, never needs host firmware
- DVB-USB binary hexline format documented (compact Intel HEX variant)
- C2 EEPROM format vs kernel hexline format comparison
- Binary comparison matrix for all 5 firmware dumps
- Anti-tampering string found in v2.13 at offset 0x1880
2026-02-11 12:18:09 -07:00
06ceaf7890 Add comprehensive Rev.2 v2.10.4 firmware deep analysis
107 functions fully inventoried via Ghidra on port 8197:
- Complete function addresses, sizes, and descriptions
- Cross-version comparison with v2.06 (61 fn) and v2.13 (88 fn)
- INT0 ISR analysis (47-byte inline USB re-enumeration)
- 27 vendor commands (0x80-0x9A) mapped and compared
- ~45 unique Rev.2 functions identified (I2C primitives, GPIO helpers)
- Rev.2 positioned as transitional between v2.06 and v2.13
2026-02-11 12:15:05 -07:00
782f5a0e8d Correct DiSEqC analysis and add complete timing chain documentation
Major correction: All firmware versions use GPIO bit-banging for DiSEqC,
NOT I2C-based control as previously reported. Deep decompilation of the
sub-functions (byte transmit, bit symbol, tone burst) across v2.06, Rev.2,
and v2.13 reveals identical Manchester encoding algorithms with only the
data GPIO pin changed per PCB revision:
  - v2.06: P0.7, Rev.2: P0.4, v2.13: P0.0
  - P0.3 (22kHz carrier gate) unchanged across all versions

New section 7: Complete DiSEqC timing chain analysis including:
  - Timer2 configuration (RCAP2=0xF82F, 4MHz clock, 500us tick)
  - Manchester encoding waveforms (3 ticks/bit, 1.5ms/bit, 667 baud)
  - Byte transmission (8 data + odd parity = 13.5ms)
  - Tone burst timing (25 ticks = 12.5ms)
  - CPU clock compensation in delay function
  - External 22kHz oscillator architecture
2026-02-11 11:11:54 -07:00
da08d1b099 Add Linux gp8psk kernel driver analysis and firmware-driver correlation
Maps all vendor USB control commands (0x80-0x9D) used by the kernel driver
against firmware implementations across all 4 extracted versions.

Key findings:
- PID 0x0203 confirmed in kernel 6.16.5 module aliases (our device)
- PID 0x0204 is a separate SkyWalker-1 hardware revision
- LOAD_BCM4500 (0x88) intentionally STALLs on Rev.2/SkyWalker hardware
- BCM4500 firmware loading protocol documented (64-byte chunked via EP0)
- Complete boot, tuning, DiSEqC, and streaming sequences mapped
2026-02-11 10:29:43 -07:00
ec4bdb8493 Add Rev.2 v2.10.4 64K Ghidra image for 8051 analysis
Parsed C2 EEPROM format (9 records, 8843 bytes) into flat 64K image.
Ghidra analysis found 107 functions - most of any firmware version.
Entry point: LJMP 0x155F, SP=0x4F, 27 vendor commands (0x80-0x9A).
INT0 ISR uses inline optimization spanning 5 unused vector slots.
2026-02-11 10:27:05 -07:00
2e00a054e8 Add comparative firmware analysis reports from Ghidra 8051 reverse engineering
Two detailed reports from analyzing all firmware variants loaded into Ghidra:

1. v2.06 vs v2.13 FW1 comparative analysis:
   - Complete vendor command dispatch table mapping (0x80-0x9D)
   - 3 new commands in v2.13: GET_DEMOD_STATUS (0x99), INIT_DEMOD (0x9A), DELAY_COMMAND (0x9C)
   - DiSEqC architecture change: GPIO bit-bang -> I2C controller
   - INT0 repurposed from USB re-enumeration to demodulator polling
   - Hardware revision detection via descriptor byte

2. v2.13 sub-variant comparison (FW1/FW2/FW3):
   - FW1: I2C-connected demodulator (original SkyWalker-1 hardware)
   - FW2: Parallel-bus demodulator via P0/P1 GPIO
   - FW3: Enhanced parallel-bus with dual-phase read and OR accumulation
   - All three support identical modulation types, differ only in hardware interface
2026-02-11 06:44:26 -07:00
4447d2c0e7 Extract firmware from official Genpix updater EXEs via Wine memory dump
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).
2026-02-11 06:05:13 -07:00
ba37105e2a Extract real FX2 firmware from I2C EEPROM
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)
2026-02-11 05:08:20 -07:00
757da08987 Add FX2 firmware dumps and USB probe tool
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.
2026-02-11 04:51:34 -07:00
f1674c21a3 Initial commit: Genpix SkyWalker-1 DVB-S driver source and DiSEqC docs
Includes original BDA driver source (headers, C++ implementation, INF
installer files), DiSEqC implementation PDF with extracted markdown
and SVG vector graphics.
2026-02-11 04:22:13 -07:00