Normalize line endings to LF across entire repository

Apply .gitattributes normalization to convert all CRLF line
endings inherited from Windows-origin source files to Unix LF.
175 files, zero content changes.
This commit is contained in:
Ryan Malloy 2026-02-20 10:55:50 -07:00
parent 696d2dd387
commit bbdcb243dc
175 changed files with 56794 additions and 56794 deletions

44
.gitignore vendored
View File

@ -1,22 +1,22 @@
# Empty extraction directories # Empty extraction directories
docs/diseqc/images/ docs/diseqc/images/
# Third-party dependencies # Third-party dependencies
firmware/fx2lib/ firmware/fx2lib/
# Build artifacts # Build artifacts
firmware/build/ firmware/build/
tools/__pycache__/ tools/__pycache__/
# TUI # TUI
tui/.venv/ tui/.venv/
tui/__pycache__/ tui/__pycache__/
# MCP server # MCP server
mcp/skywalker-mcp/.venv/ mcp/skywalker-mcp/.venv/
mcp/skywalker-mcp/__pycache__/ mcp/skywalker-mcp/__pycache__/
# Documentation site # Documentation site
site/node_modules/ site/node_modules/
site/dist/ site/dist/
site/.astro/ site/.astro/

358
README.md
View File

@ -1,179 +1,179 @@
<div align="center"> <div align="center">
# SkyWalker-1 # SkyWalker-1
**Reverse-engineered documentation, custom firmware, and Python tooling for the Genpix SkyWalker-1 DVB-S USB 2.0 satellite receiver.** **Reverse-engineered documentation, custom firmware, and Python tooling for the Genpix SkyWalker-1 DVB-S USB 2.0 satellite receiver.**
[![Docs](https://img.shields.io/badge/docs-skywalker--1.warehack.ing-0a7e8c?style=flat-square)](https://skywalker-1.warehack.ing) [![Docs](https://img.shields.io/badge/docs-skywalker--1.warehack.ing-0a7e8c?style=flat-square)](https://skywalker-1.warehack.ing)
[![Firmware](https://img.shields.io/badge/firmware-SDCC%20%2B%20fx2lib-1a1a2e?style=flat-square)](https://skywalker-1.warehack.ing/firmware/custom-v301/) [![Firmware](https://img.shields.io/badge/firmware-SDCC%20%2B%20fx2lib-1a1a2e?style=flat-square)](https://skywalker-1.warehack.ing/firmware/custom-v301/)
[![License](https://img.shields.io/badge/license-open--source-3d5a80?style=flat-square)](#license) [![License](https://img.shields.io/badge/license-open--source-3d5a80?style=flat-square)](#license)
</div> </div>
--- ---
The SkyWalker-1 is a standalone USB 2.0 DVB-S receiver built around a **Cypress FX2LP** (CY7C68013A) microcontroller and **Broadcom BCM4500** satellite demodulator. It was designed by [Genpix Electronics](https://www.genpix-electronics.com/index.php?act=viewDoc&docId=9) for DVB-S, Turbo-coded, Digicipher II, and DSS reception. The SkyWalker-1 is a standalone USB 2.0 DVB-S receiver built around a **Cypress FX2LP** (CY7C68013A) microcontroller and **Broadcom BCM4500** satellite demodulator. It was designed by [Genpix Electronics](https://www.genpix-electronics.com/index.php?act=viewDoc&docId=9) for DVB-S, Turbo-coded, Digicipher II, and DSS reception.
This project documents the device's complete internal architecture -- every vendor command, register, GPIO pin, and data path -- built up from Linux kernel driver analysis, Ghidra firmware disassembly of five firmware images, Windows BDA driver source review, and original custom firmware development. This project documents the device's complete internal architecture -- every vendor command, register, GPIO pin, and data path -- built up from Linux kernel driver analysis, Ghidra firmware disassembly of five firmware images, Windows BDA driver source review, and original custom firmware development.
**[Browse the full documentation at skywalker-1.warehack.ing](https://skywalker-1.warehack.ing)** **[Browse the full documentation at skywalker-1.warehack.ing](https://skywalker-1.warehack.ing)**
## What's Here ## What's Here
``` ```
skywalker-1/ skywalker-1/
firmware/ Custom FX2 firmware (SDCC + fx2lib, 1441 lines of C) firmware/ Custom FX2 firmware (SDCC + fx2lib, 1441 lines of C)
skywalker1.c Full replacement firmware with 10 custom vendor commands skywalker1.c Full replacement firmware with 10 custom vendor commands
Makefile Build rules targeting CY7C68013A Makefile Build rules targeting CY7C68013A
dscr.a51 USB descriptors (VID 0x09C0, PID 0x0203) dscr.a51 USB descriptors (VID 0x09C0, PID 0x0203)
firmware-dump/ Extracted stock firmware binaries (v2.06, v2.10, v2.13 x3) firmware-dump/ Extracted stock firmware binaries (v2.06, v2.10, v2.13 x3)
firmware-driver/ Genpix Windows BDA driver source (reference material) firmware-driver/ Genpix Windows BDA driver source (reference material)
tools/ Python utilities for direct hardware interaction tools/ Python utilities for direct hardware interaction
skywalker.py Multi-mode RF tool: spectrum, scan, monitor, lband, track skywalker.py Multi-mode RF tool: spectrum, scan, monitor, lband, track
skywalker_lib.py Shared library: USB transport, BCM4500 register access skywalker_lib.py Shared library: USB transport, BCM4500 register access
fw_load.py FX2 RAM firmware loader via 0xA0 vendor request fw_load.py FX2 RAM firmware loader via 0xA0 vendor request
tune.py Transponder tuner with lock detection and BER readout tune.py Transponder tuner with lock detection and BER readout
ts_analyze.py MPEG-2 transport stream parser and PID analyzer ts_analyze.py MPEG-2 transport stream parser and PID analyzer
eeprom_dump.py Full EEPROM image extraction eeprom_dump.py Full EEPROM image extraction
eeprom_write.py EEPROM flash tool with C2 format support eeprom_write.py EEPROM flash tool with C2 format support
wine_memdump.py Extract firmware from Genpix Windows updater EXEs wine_memdump.py Extract firmware from Genpix Windows updater EXEs
test_*.py Boot sequence and I2C debug/isolation harnesses test_*.py Boot sequence and I2C debug/isolation harnesses
site/ Astro Starlight documentation (37 pages, 9 sections) site/ Astro Starlight documentation (37 pages, 9 sections)
docs/ Raw analysis documents and master hardware reference docs/ Raw analysis documents and master hardware reference
``` ```
## Hardware at a Glance ## Hardware at a Glance
| | | | | |
|---|---| |---|---|
| **MCU** | Cypress CY7C68013A (FX2LP) -- 8051 core at 48 MHz, USB 2.0 Hi-Speed | | **MCU** | Cypress CY7C68013A (FX2LP) -- 8051 core at 48 MHz, USB 2.0 Hi-Speed |
| **Demodulator** | Broadcom BCM4500 -- DVB-S / Turbo / DCII / DSS, 128-pin MQFP | | **Demodulator** | Broadcom BCM4500 -- DVB-S / Turbo / DCII / DSS, 128-pin MQFP |
| **IF Range** | 950 -- 2150 MHz | | **IF Range** | 950 -- 2150 MHz |
| **Symbol Rate** | 256 Ksps -- 30 Msps | | **Symbol Rate** | 256 Ksps -- 30 Msps |
| **LNB Control** | 13/18V, 22 kHz tone, DiSEqC 1.0/1.2, legacy switches | | **LNB Control** | 13/18V, 22 kHz tone, DiSEqC 1.0/1.2, legacy switches |
| **Connector** | IEC F-type female | | **Connector** | IEC F-type female |
| **Transport** | 8-bit parallel bus via GPIF into USB bulk endpoint EP2 | | **Transport** | 8-bit parallel bus via GPIF into USB bulk endpoint EP2 |
``` ```
+--[ I2C EEPROM 0x51 ] +--[ I2C EEPROM 0x51 ]
| |
USB 2.0 HS | I2C Bus (400 kHz) USB 2.0 HS | I2C Bus (400 kHz)
Host PC <----> [ CY7C68013A FX2LP ] <-----> [ BCM4500 Demod 0x08 ] Host PC <----> [ CY7C68013A FX2LP ] <-----> [ BCM4500 Demod 0x08 ]
| 8051 @ 48 MHz | | | 8051 @ 48 MHz | |
| GPIF Engine |<-----------+ 8-bit parallel TS | GPIF Engine |<-----------+ 8-bit parallel TS
| EP2 Bulk IN | | EP2 Bulk IN |
| GPIO (P0/P3) |---> [ 22 kHz Osc ] ---> LNB/Coax | GPIO (P0/P3) |---> [ 22 kHz Osc ] ---> LNB/Coax
| |---> [ LNB Voltage Ctrl ] | |---> [ LNB Voltage Ctrl ]
+-----------------+ +-----------------+
| |
+--[ Tuner/LNB IC 0x10 ] +--[ Tuner/LNB IC 0x10 ]
``` ```
**Supported modulations:** DVB-S (QPSK), DVB-S (BPSK), Turbo QPSK, Turbo 8PSK, Turbo 16QAM, Digicipher II (Combo, Split I/Q, Offset QPSK), DSS (QPSK). **Supported modulations:** DVB-S (QPSK), DVB-S (BPSK), Turbo QPSK, Turbo 8PSK, Turbo 16QAM, Digicipher II (Combo, Split I/Q, Offset QPSK), DSS (QPSK).
> DVB-S2 is **not supported**. The BCM4500 predates DVB-S2 and contains no LDPC or BCH decoder hardware. This is a silicon limitation -- no firmware update can change it. See the [DVB-S2 investigation](https://skywalker-1.warehack.ing/driver/dvb-s2/). > DVB-S2 is **not supported**. The BCM4500 predates DVB-S2 and contains no LDPC or BCH decoder hardware. This is a silicon limitation -- no firmware update can change it. See the [DVB-S2 investigation](https://skywalker-1.warehack.ing/driver/dvb-s2/).
## Custom Firmware ## Custom Firmware
The stock EEPROM firmware was replaced with an open-source implementation built from scratch using **SDCC** and **fx2lib**. It implements all stock vendor commands (kernel driver compatible) plus 10 new diagnostic and analysis commands: The stock EEPROM firmware was replaced with an open-source implementation built from scratch using **SDCC** and **fx2lib**. It implements all stock vendor commands (kernel driver compatible) plus 10 new diagnostic and analysis commands:
| Command | ID | Purpose | | Command | ID | Purpose |
|---------|-----|---------| |---------|-----|---------|
| Spectrum Sweep | `0xB0` | AGC-based power sweep across IF range | | Spectrum Sweep | `0xB0` | AGC-based power sweep across IF range |
| Raw Demod Read | `0xB1` | Direct BCM4500 indirect register read | | Raw Demod Read | `0xB1` | Direct BCM4500 indirect register read |
| Raw Demod Write | `0xB2` | Direct BCM4500 indirect register write | | Raw Demod Write | `0xB2` | Direct BCM4500 indirect register write |
| Blind Scan | `0xB3` | Carrier detection at arbitrary frequency | | Blind Scan | `0xB3` | Carrier detection at arbitrary frequency |
| Signal Monitor | `0xB7` | Combined SNR + AGC + lock in single transfer | | Signal Monitor | `0xB7` | Combined SNR + AGC + lock in single transfer |
| Tune Monitor | `0xB8` | Tune + dwell + measure in one round-trip | | Tune Monitor | `0xB8` | Tune + dwell + measure in one round-trip |
| Multi Reg Read | `0xB9` | Batch read of contiguous indirect registers | | Multi Reg Read | `0xB9` | Batch read of contiguous indirect registers |
Build and load: Build and load:
```bash ```bash
cd firmware cd firmware
make # requires SDCC + fx2lib make # requires SDCC + fx2lib
make load # RAM-loads via fw_load.py (does not touch EEPROM) make load # RAM-loads via fw_load.py (does not touch EEPROM)
``` ```
## Python Tools ## Python Tools
All tools communicate directly with the SkyWalker-1 over USB using `pyusb`. No kernel driver required. All tools communicate directly with the SkyWalker-1 over USB using `pyusb`. No kernel driver required.
```bash ```bash
# Load custom firmware into FX2 RAM # Load custom firmware into FX2 RAM
python tools/fw_load.py firmware/build/skywalker1.bix python tools/fw_load.py firmware/build/skywalker1.bix
# Tune to a transponder and check lock # Tune to a transponder and check lock
python tools/tune.py --freq 12224 --sr 20000 --pol H --mod dvb-s python tools/tune.py --freq 12224 --sr 20000 --pol H --mod dvb-s
# Sweep the IF band and render ASCII spectrum # Sweep the IF band and render ASCII spectrum
python tools/skywalker.py spectrum --start 950 --stop 2150 --step 5 python tools/skywalker.py spectrum --start 950 --stop 2150 --step 5
# Real-time signal strength (dish alignment) # Real-time signal strength (dish alignment)
python tools/skywalker.py monitor --freq 1175 python tools/skywalker.py monitor --freq 1175
# Dump full EEPROM contents # Dump full EEPROM contents
python tools/eeprom_dump.py --output eeprom.bin python tools/eeprom_dump.py --output eeprom.bin
``` ```
The `skywalker.py` multi-mode tool provides five operating modes: `spectrum` (sweep analyzer), `scan` (transponder finder), `monitor` (signal strength meter), `lband` (direct L-band input), and `track` (carrier/beacon tracker with CSV logging). The `skywalker.py` multi-mode tool provides five operating modes: `spectrum` (sweep analyzer), `scan` (transponder finder), `monitor` (signal strength meter), `lband` (direct L-band input), and `track` (carrier/beacon tracker with CSV logging).
## Documentation Site ## Documentation Site
The full documentation is published at **[skywalker-1.warehack.ing](https://skywalker-1.warehack.ing)** and covers: The full documentation is published at **[skywalker-1.warehack.ing](https://skywalker-1.warehack.ing)** and covers:
| Section | Pages | Covers | | Section | Pages | Covers |
|---------|-------|--------| |---------|-------|--------|
| **Hardware** | 4 | Board architecture, GPIO pin map, RF specifications | | **Hardware** | 4 | Board architecture, GPIO pin map, RF specifications |
| **USB Interface** | 4 | 30 vendor commands, boot sequence, endpoint layout | | **USB Interface** | 4 | 30 vendor commands, boot sequence, endpoint layout |
| **BCM4500** | 5 | Register map, indirect access protocol, tuning sequence, GPIF streaming, signal monitoring | | **BCM4500** | 5 | Register map, indirect access protocol, tuning sequence, GPIF streaming, signal monitoring |
| **LNB & DiSEqC** | 3 | Voltage/tone control, DiSEqC 1.0/1.2, legacy Dish switches | | **LNB & DiSEqC** | 3 | Voltage/tone control, DiSEqC 1.0/1.2, legacy Dish switches |
| **I2C Bus** | 2 | Bus architecture, STOP corruption bug root cause analysis | | **I2C Bus** | 2 | Bus architecture, STOP corruption bug root cause analysis |
| **Firmware** | 7 | 5 stock versions compared, custom v3.01 and v3.02, storage formats | | **Firmware** | 7 | 5 stock versions compared, custom v3.01 and v3.02, storage formats |
| **Driver** | 2 | Linux gp8psk kernel driver, DVB-S2 incompatibility investigation | | **Driver** | 2 | Linux gp8psk kernel driver, DVB-S2 incompatibility investigation |
| **Tools** | 7 | Every Python utility documented with usage examples | | **Tools** | 7 | Every Python utility documented with usage examples |
| **Reference** | 1 | Consolidated master reference (registers, commands, GPIO, I2C) | | **Reference** | 1 | Consolidated master reference (registers, commands, GPIO, I2C) |
To run the docs site locally: To run the docs site locally:
```bash ```bash
cd site cd site
npm install npm install
npm run dev # http://localhost:4321 npm run dev # http://localhost:4321
``` ```
<details> <details>
<summary>Docker deployment</summary> <summary>Docker deployment</summary>
The docs site includes a multi-stage Dockerfile with dev and prod targets. Production serves static files through Caddy. The docs site includes a multi-stage Dockerfile with dev and prod targets. Production serves static files through Caddy.
```bash ```bash
cd site cd site
# Development (HMR via volume mounts) # Development (HMR via volume mounts)
APP_ENV=dev docker compose up --build APP_ENV=dev docker compose up --build
# Production (static build served by Caddy) # Production (static build served by Caddy)
APP_ENV=prod docker compose up --build -d APP_ENV=prod docker compose up --build -d
``` ```
</details> </details>
## Project History ## Project History
This project started with USB packet captures and `lsusb` output, then progressed through increasingly deep layers of the hardware: This project started with USB packet captures and `lsusb` output, then progressed through increasingly deep layers of the hardware:
1. **EEPROM extraction** -- dumped raw firmware bytes over I2C 1. **EEPROM extraction** -- dumped raw firmware bytes over I2C
2. **Ghidra disassembly** -- decompiled five 8051 firmware images, mapped all functions and vendor commands 2. **Ghidra disassembly** -- decompiled five 8051 firmware images, mapped all functions and vendor commands
3. **Windows driver analysis** -- cross-referenced Ghidra findings against Genpix BDA driver source 3. **Windows driver analysis** -- cross-referenced Ghidra findings against Genpix BDA driver source
4. **Linux driver analysis** -- mapped kernel `gp8psk` driver to decoded vendor commands 4. **Linux driver analysis** -- mapped kernel `gp8psk` driver to decoded vendor commands
5. **Custom firmware** -- wrote a full replacement in C, discovered and fixed the [I2C STOP corruption bug](https://skywalker-1.warehack.ing/i2c/stop-corruption-bug/) 5. **Custom firmware** -- wrote a full replacement in C, discovered and fixed the [I2C STOP corruption bug](https://skywalker-1.warehack.ing/i2c/stop-corruption-bug/)
6. **RF tooling** -- built spectrum analyzer, blind scanner, and signal monitor on top of the custom command set 6. **RF tooling** -- built spectrum analyzer, blind scanner, and signal monitor on top of the custom command set
## Contributing ## Contributing
This is a niche reverse-engineering project for a specific piece of satellite hardware. If you have a SkyWalker-1 (or other Genpix device using the BCM4500), contributions are welcome -- particularly additional firmware dumps, register documentation, or corrections to the analysis. This is a niche reverse-engineering project for a specific piece of satellite hardware. If you have a SkyWalker-1 (or other Genpix device using the BCM4500), contributions are welcome -- particularly additional firmware dumps, register documentation, or corrections to the analysis.
## License ## License
The custom firmware source, Python tools, and documentation are open source. Stock firmware binaries in `firmware-dump/` are proprietary Genpix Electronics images retained for research and interoperability purposes. The custom firmware source, Python tools, and documentation are open source. Stock firmware binaries in `firmware-dump/` are proprietary Genpix Electronics images retained for research and interoperability purposes.

View File

@ -1,257 +1,257 @@
# BOOT_8PSK Debugging Findings # BOOT_8PSK Debugging Findings
Technical reference for the BCM4500 demodulator boot sequence on the Genpix SkyWalker-1 (Cypress FX2 CY7C68013A + Broadcom BCM4500), firmware v3.01.0. Documents the root cause analysis of a firmware hang during I2C initialization and the fixes applied. Technical reference for the BCM4500 demodulator boot sequence on the Genpix SkyWalker-1 (Cypress FX2 CY7C68013A + Broadcom BCM4500), firmware v3.01.0. Documents the root cause analysis of a firmware hang during I2C initialization and the fixes applied.
**Hardware:** Genpix SkyWalker-1 USB 2.0 DVB-S receiver **Hardware:** Genpix SkyWalker-1 USB 2.0 DVB-S receiver
**MCU:** Cypress CY7C68013A (FX2LP), 8051 core at 48MHz **MCU:** Cypress CY7C68013A (FX2LP), 8051 core at 48MHz
**Demodulator:** Broadcom BCM4500 **Demodulator:** Broadcom BCM4500
**Firmware:** Custom v3.01.0 (SDCC + fx2lib) **Firmware:** Custom v3.01.0 (SDCC + fx2lib)
**I2C bus speed:** 400kHz **I2C bus speed:** 400kHz
--- ---
## The Problem ## The Problem
Custom firmware v3.01.0 implements vendor command `BOOT_8PSK` (bRequest=0x89, wValue=1), which powers on the BCM4500 demodulator and initializes it via I2C. When first tested, this command caused the FX2 firmware to hang for over 10 seconds, making the USB device completely unresponsive -- no vendor command would return, and the host-side USB stack would report timeout errors. Custom firmware v3.01.0 implements vendor command `BOOT_8PSK` (bRequest=0x89, wValue=1), which powers on the BCM4500 demodulator and initializes it via I2C. When first tested, this command caused the FX2 firmware to hang for over 10 seconds, making the USB device completely unresponsive -- no vendor command would return, and the host-side USB stack would report timeout errors.
The initial suspicion was infinite I2C loops. The fx2lib I2C library uses bare `while` loops that poll hardware status bits with no timeout: The initial suspicion was infinite I2C loops. The fx2lib I2C library uses bare `while` loops that poll hardware status bits with no timeout:
```c ```c
// fx2lib/lib/i2c.c -- original code // fx2lib/lib/i2c.c -- original code
while ( !(I2CS & bmDONE) && !cancel_i2c_trans); while ( !(I2CS & bmDONE) && !cancel_i2c_trans);
``` ```
The `cancel_i2c_trans` variable is intended as an external abort mechanism, but nothing in the firmware sets it during normal operation. If the I2C controller never asserts `bmDONE` (for example, because a slave is holding SCL low), the firmware spins indefinitely in this loop. The `cancel_i2c_trans` variable is intended as an external abort mechanism, but nothing in the firmware sets it during normal operation. If the I2C controller never asserts `bmDONE` (for example, because a slave is holding SCL low), the firmware spins indefinitely in this loop.
Adding I2C timeout protection (described below) eliminated the infinite-hang symptom, but the boot sequence still failed: the BCM4500 probe read returned NACK, and all three register initialization blocks failed. Adding I2C timeout protection (described below) eliminated the infinite-hang symptom, but the boot sequence still failed: the BCM4500 probe read returned NACK, and all three register initialization blocks failed.
## Root Cause: Spurious I2C STOP Condition ## Root Cause: Spurious I2C STOP Condition
The boot function originally included a so-called "I2C bus reset" step before any I2C communication: The boot function originally included a so-called "I2C bus reset" step before any I2C communication:
```c ```c
I2CS |= bmSTOP; I2CS |= bmSTOP;
i2c_wait_stop(); i2c_wait_stop();
``` ```
This pattern appears in various FX2 example code and seems reasonable on its face -- send a STOP condition to ensure the I2C bus is in a known idle state before starting fresh. On the FX2's I2C controller hardware, this is incorrect. This pattern appears in various FX2 example code and seems reasonable on its face -- send a STOP condition to ensure the I2C bus is in a known idle state before starting fresh. On the FX2's I2C controller hardware, this is incorrect.
### Incremental Debug Modes ### Incremental Debug Modes
The root cause was discovered through a series of incremental debug modes added to the `BOOT_8PSK` vendor command handler. Each mode executes a subset of the full boot sequence, isolating which step introduces the failure: The root cause was discovered through a series of incremental debug modes added to the `BOOT_8PSK` vendor command handler. Each mode executes a subset of the full boot sequence, isolating which step introduces the failure:
| wValue | Action | Result | | wValue | Action | Result |
|--------|--------|--------| |--------|--------|--------|
| `0x80` | No-op: return `config_status` and `boot_stage` only | Works | | `0x80` | No-op: return `config_status` and `boot_stage` only | Works |
| `0x81` | GPIO + power + delays only (no I2C at all) | Works | | `0x81` | GPIO + power + delays only (no I2C at all) | Works |
| `0x82` | GPIO + power + `bmSTOP` + I2C probe read | **Fails** | | `0x82` | GPIO + power + `bmSTOP` + I2C probe read | **Fails** |
| `0x83` | GPIO + power + `bmSTOP` + probe + init block 0 | **Fails** (same root cause) | | `0x83` | GPIO + power + `bmSTOP` + probe + init block 0 | **Fails** (same root cause) |
| `0x84` | `bcm_direct_read` only (no GPIO, chip already powered) | Works | | `0x84` | `bcm_direct_read` only (no GPIO, chip already powered) | Works |
| `0x85` | GPIO + power + reset, **no** `bmSTOP`, then probe | Works | | `0x85` | GPIO + power + reset, **no** `bmSTOP`, then probe | Works |
Three observations clinch the diagnosis: Three observations clinch the diagnosis:
1. **Mode 0x82 fails but mode 0x85 succeeds.** These two modes are identical except that 0x82 issues `I2CS |= bmSTOP` before the probe read and 0x85 does not. The `bmSTOP` is the only difference, and it is the only thing that breaks I2C. 1. **Mode 0x82 fails but mode 0x85 succeeds.** These two modes are identical except that 0x82 issues `I2CS |= bmSTOP` before the probe read and 0x85 does not. The `bmSTOP` is the only difference, and it is the only thing that breaks I2C.
2. **Mode 0x84 succeeds immediately after 0x82 fails.** Mode 0x84 calls `bcm_direct_read` with no GPIO manipulation or bus reset -- just a plain I2C combined read. If called after a failed 0x82, it succeeds. This proves two things: the BCM4500 is alive and responding on I2C, and the `i2c_combined_read` function itself is correct. The failure in 0x82 is not a timing or power issue. 2. **Mode 0x84 succeeds immediately after 0x82 fails.** Mode 0x84 calls `bcm_direct_read` with no GPIO manipulation or bus reset -- just a plain I2C combined read. If called after a failed 0x82, it succeeds. This proves two things: the BCM4500 is alive and responding on I2C, and the `i2c_combined_read` function itself is correct. The failure in 0x82 is not a timing or power issue.
3. **Raw I2C reads via vendor command 0xB5 succeed after 0x82 fails.** Command 0xB5 uses the same `i2c_combined_read` function as `bcm_direct_read`. Running it from the host side after a failed 0x82 returns valid data from the BCM4500. This confirms the chip was alive the whole time -- the FX2's I2C controller was in a bad state, not the bus or the slave. 3. **Raw I2C reads via vendor command 0xB5 succeed after 0x82 fails.** Command 0xB5 uses the same `i2c_combined_read` function as `bcm_direct_read`. Running it from the host side after a failed 0x82 returns valid data from the BCM4500. This confirms the chip was alive the whole time -- the FX2's I2C controller was in a bad state, not the bus or the slave.
The test scripts that drove this investigation are in the `tools/` directory: The test scripts that drove this investigation are in the `tools/` directory:
- `test_boot_debug.py` -- sends debug modes 0x80 through 0x83 sequentially - `test_boot_debug.py` -- sends debug modes 0x80 through 0x83 sequentially
- `test_i2c_debug.py` -- powers on via 0x81, runs bus scans, tests probe timing - `test_i2c_debug.py` -- powers on via 0x81, runs bus scans, tests probe timing
- `test_i2c_isolate.py` -- tests whether re-reset or insufficient delay causes failure - `test_i2c_isolate.py` -- tests whether re-reset or insufficient delay causes failure
- `test_i2c_pinpoint.py` -- the definitive test: compares 0x84, 0x85, and 0x82 - `test_i2c_pinpoint.py` -- the definitive test: compares 0x84, 0x85, and 0x82
### What Happens Inside the FX2 I2C Controller ### What Happens Inside the FX2 I2C Controller
The FX2's I2C master controller is a hardware peripheral accessed through the `I2CS`, `I2DAT`, and `I2CTL` SFRs. The controller implements an I2C state machine in silicon. Writing `bmSTOP` to `I2CS` instructs the hardware to generate a STOP condition (SDA rising while SCL is high). The FX2's I2C master controller is a hardware peripheral accessed through the `I2CS`, `I2DAT`, and `I2CTL` SFRs. The controller implements an I2C state machine in silicon. Writing `bmSTOP` to `I2CS` instructs the hardware to generate a STOP condition (SDA rising while SCL is high).
When no I2C transaction is active -- no prior START has been issued, and the bus is idle -- writing `bmSTOP` puts the controller into an inconsistent internal state. The `bmSTOP` bit may not clear properly (it is supposed to self-clear when the STOP condition completes on the bus), and subsequent START conditions fail to generate proper clock sequences or detect ACK from slaves. When no I2C transaction is active -- no prior START has been issued, and the bus is idle -- writing `bmSTOP` puts the controller into an inconsistent internal state. The `bmSTOP` bit may not clear properly (it is supposed to self-clear when the STOP condition completes on the bus), and subsequent START conditions fail to generate proper clock sequences or detect ACK from slaves.
The Cypress TRM (EZ-USB Technical Reference Manual) does not explicitly warn against this, but the I2C chapter describes STOP as a step that follows a completed read or write transaction. It is not documented as a standalone bus-reset mechanism. The Cypress TRM (EZ-USB Technical Reference Manual) does not explicitly warn against this, but the I2C chapter describes STOP as a step that follows a completed read or write transaction. It is not documented as a standalone bus-reset mechanism.
The correct way to ensure a clean I2C bus state on the FX2 is to simply proceed with a new START condition. If the bus is idle (which it will be after power-on or after the previous transaction completed normally), the START succeeds and the controller enters its normal operating state. The hardware handles bus arbitration automatically on START. The correct way to ensure a clean I2C bus state on the FX2 is to simply proceed with a new START condition. If the bus is idle (which it will be after power-on or after the previous transaction completed normally), the START succeeds and the controller enters its normal operating state. The hardware handles bus arbitration automatically on START.
## The Fix ## The Fix
The fix is a single deletion. Remove the spurious STOP from the boot sequence: The fix is a single deletion. Remove the spurious STOP from the boot sequence:
```c ```c
/* BEFORE (broken): */ /* BEFORE (broken): */
I2CS |= bmSTOP; I2CS |= bmSTOP;
i2c_wait_stop(); i2c_wait_stop();
/* AFTER (correct): */ /* AFTER (correct): */
/* NOTE: Do NOT send I2CS bmSTOP here. Sending STOP when no transaction /* NOTE: Do NOT send I2CS bmSTOP here. Sending STOP when no transaction
* is active corrupts the FX2 I2C controller state, causing subsequent * is active corrupts the FX2 I2C controller state, causing subsequent
* START+ACK detection to fail. The I2C bus will be in a clean state * START+ACK detection to fail. The I2C bus will be in a clean state
* when we reach the probe step -- any prior transaction ended with STOP. */ * when we reach the probe step -- any prior transaction ended with STOP. */
``` ```
The corrected `bcm4500_boot()` function proceeds directly from GPIO/power setup to the I2C probe read without any bus-reset step: The corrected `bcm4500_boot()` function proceeds directly from GPIO/power setup to the I2C probe read without any bus-reset step:
```c ```c
static BOOL bcm4500_boot(void) { static BOOL bcm4500_boot(void) {
boot_stage = 1; boot_stage = 1;
cancel_i2c_trans = FALSE; cancel_i2c_trans = FALSE;
/* P3.7, P3.6, P3.5 HIGH (idle state for control lines) */ /* P3.7, P3.6, P3.5 HIGH (idle state for control lines) */
IOD |= 0xE0; IOD |= 0xE0;
/* Assert BCM4500 hardware RESET (P0.5 LOW) */ /* Assert BCM4500 hardware RESET (P0.5 LOW) */
OEA |= PIN_BCM_RESET; OEA |= PIN_BCM_RESET;
IOA &= ~PIN_BCM_RESET; IOA &= ~PIN_BCM_RESET;
/* No I2CS bmSTOP here -- see note above */ /* No I2CS bmSTOP here -- see note above */
/* Power on: P0.1 HIGH (enable), P0.2 LOW (disable off) */ /* Power on: P0.1 HIGH (enable), P0.2 LOW (disable off) */
OEA |= (PIN_PWR_EN | PIN_PWR_DIS); OEA |= (PIN_PWR_EN | PIN_PWR_DIS);
IOA = (IOA & ~PIN_PWR_DIS) | PIN_PWR_EN; IOA = (IOA & ~PIN_PWR_DIS) | PIN_PWR_EN;
boot_stage = 2; boot_stage = 2;
delay(30); /* power settle */ delay(30); /* power settle */
IOA |= PIN_BCM_RESET; /* release reset */ IOA |= PIN_BCM_RESET; /* release reset */
delay(50); /* BCM4500 POR + mask ROM boot */ delay(50); /* BCM4500 POR + mask ROM boot */
boot_stage = 3; boot_stage = 3;
/* I2C probe -- if this fails, the chip didn't come out of reset */ /* I2C probe -- if this fails, the chip didn't come out of reset */
if (!bcm_direct_read(BCM_REG_STATUS, &i2c_rd[0])) if (!bcm_direct_read(BCM_REG_STATUS, &i2c_rd[0]))
return FALSE; return FALSE;
/* ... register init blocks follow ... */ /* ... register init blocks follow ... */
} }
``` ```
## I2C Timeout Protection ## I2C Timeout Protection
Even with the `bmSTOP` fix, timeout protection on all I2C operations is essential. The FX2's I2C controller has no hardware timeout -- if a slave device holds SCL low (clock stretching), or if an electrical fault prevents `bmDONE` from asserting, the firmware will spin forever in a polling loop. Even with the `bmSTOP` fix, timeout protection on all I2C operations is essential. The FX2's I2C controller has no hardware timeout -- if a slave device holds SCL low (clock stretching), or if an electrical fault prevents `bmDONE` from asserting, the firmware will spin forever in a polling loop.
### The Problem with fx2lib ### The Problem with fx2lib
The fx2lib `i2c_write()` and `i2c_read()` functions poll `bmDONE` and `bmSTOP` with loops like: The fx2lib `i2c_write()` and `i2c_read()` functions poll `bmDONE` and `bmSTOP` with loops like:
```c ```c
while ( !(I2CS & bmDONE) && !cancel_i2c_trans); while ( !(I2CS & bmDONE) && !cancel_i2c_trans);
``` ```
The `cancel_i2c_trans` flag is declared as `volatile __xdata BOOL` and is set to `FALSE` at the start of each transaction. The library documentation says firmware can set it to `TRUE` from an interrupt to abort a stuck transaction. In practice, nothing in the firmware sets it, so these loops are effectively: The `cancel_i2c_trans` flag is declared as `volatile __xdata BOOL` and is set to `FALSE` at the start of each transaction. The library documentation says firmware can set it to `TRUE` from an interrupt to abort a stuck transaction. In practice, nothing in the firmware sets it, so these loops are effectively:
```c ```c
while (!(I2CS & bmDONE)); // infinite if bmDONE never asserts while (!(I2CS & bmDONE)); // infinite if bmDONE never asserts
``` ```
### Timeout-Protected Replacements ### Timeout-Protected Replacements
The custom firmware replaces all fx2lib I2C functions with timeout-protected wrappers: The custom firmware replaces all fx2lib I2C functions with timeout-protected wrappers:
```c ```c
#define I2C_TIMEOUT 6000 #define I2C_TIMEOUT 6000
static BOOL i2c_wait_done(void) { static BOOL i2c_wait_done(void) {
WORD timeout = I2C_TIMEOUT; WORD timeout = I2C_TIMEOUT;
while (!(I2CS & bmDONE)) { while (!(I2CS & bmDONE)) {
if (--timeout == 0) if (--timeout == 0)
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
static BOOL i2c_wait_stop(void) { static BOOL i2c_wait_stop(void) {
WORD timeout = I2C_TIMEOUT; WORD timeout = I2C_TIMEOUT;
while (I2CS & bmSTOP) { while (I2CS & bmSTOP) {
if (--timeout == 0) if (--timeout == 0)
return FALSE; return FALSE;
} }
return TRUE; return TRUE;
} }
``` ```
A `WORD` counter of 6000, decremented in a tight SDCC-compiled loop at 48MHz (4 clocks per 8051 machine cycle, ~12 MIPS), gives approximately 5-10ms per wait. At 400kHz I2C, a single byte transfer (9 clock pulses) takes 22.5 microseconds, so this timeout provides well over 200x margin for normal operations while still bounding the worst case. A `WORD` counter of 6000, decremented in a tight SDCC-compiled loop at 48MHz (4 clocks per 8051 machine cycle, ~12 MIPS), gives approximately 5-10ms per wait. At 400kHz I2C, a single byte transfer (9 clock pulses) takes 22.5 microseconds, so this timeout provides well over 200x margin for normal operations while still bounding the worst case.
All BCM4500 I2C operations -- `i2c_combined_read`, `i2c_write_timeout`, `i2c_write_multi_timeout` -- use these timeout-protected waits and return `FALSE` on timeout, allowing the caller to report failure rather than hanging the firmware. All BCM4500 I2C operations -- `i2c_combined_read`, `i2c_write_timeout`, `i2c_write_multi_timeout` -- use these timeout-protected waits and return `FALSE` on timeout, allowing the caller to report failure rather than hanging the firmware.
## Kernel Driver Race Condition ## Kernel Driver Race Condition
The `dvb_usb_gp8psk` kernel module auto-loads via udev when VID:PID `09C0:0203` appears on the USB bus. This happens every time the FX2 re-enumerates after firmware load. The kernel driver races with the test tools and sends its own `BOOT_8PSK` command (along with other initialization), which interferes with debugging. The `dvb_usb_gp8psk` kernel module auto-loads via udev when VID:PID `09C0:0203` appears on the USB bus. This happens every time the FX2 re-enumerates after firmware load. The kernel driver races with the test tools and sends its own `BOOT_8PSK` command (along with other initialization), which interferes with debugging.
Symptoms of this race condition: Symptoms of this race condition:
- Test scripts report "resource busy" or "entity not found" errors - Test scripts report "resource busy" or "entity not found" errors
- The BCM4500 enters an unexpected state because the kernel driver partially initialized it - The BCM4500 enters an unexpected state because the kernel driver partially initialized it
- The kernel driver detaches from the device mid-test - The kernel driver detaches from the device mid-test
The fix is to blacklist the module: The fix is to blacklist the module:
``` ```
# /etc/modprobe.d/blacklist-gp8psk.conf # /etc/modprobe.d/blacklist-gp8psk.conf
blacklist dvb_usb_gp8psk blacklist dvb_usb_gp8psk
blacklist gp8psk_fe blacklist gp8psk_fe
``` ```
After creating this file, run `sudo modprobe -r dvb_usb_gp8psk gp8psk_fe` to unload any currently-loaded instances. The blacklist prevents udev from auto-loading the module on device insertion, giving test tools exclusive access. After creating this file, run `sudo modprobe -r dvb_usb_gp8psk gp8psk_fe` to unload any currently-loaded instances. The blacklist prevents udev from auto-loading the module on device insertion, giving test tools exclusive access.
## I2C Bus Scan Results ## I2C Bus Scan Results
Vendor command `0xB4` performs a full 7-bit I2C bus scan by attempting a START + address + WRITE to every address from 0x01 to 0x77 and checking for ACK. Three devices were found: Vendor command `0xB4` performs a full 7-bit I2C bus scan by attempting a START + address + WRITE to every address from 0x01 to 0x77 and checking for ACK. Three devices were found:
| Address | Identity | | Address | Identity |
|---------|----------| |---------|----------|
| `0x08` | BCM4500 demodulator. Status register `0xA2` returns valid data. This is the primary device for all demodulator operations. | | `0x08` | BCM4500 demodulator. Status register `0xA2` returns valid data. This is the primary device for all demodulator operations. |
| `0x10` | Likely the tuner or LNB controller. The SkyWalker-1 uses a separate tuner IC (accessed through the BCM4500 in normal operation, but also directly addressable on the shared I2C bus). | | `0x10` | Likely the tuner or LNB controller. The SkyWalker-1 uses a separate tuner IC (accessed through the BCM4500 in normal operation, but also directly addressable on the shared I2C bus). |
| `0x51` | Likely a configuration EEPROM. Many DVB-S receivers store tuner calibration data or device serial numbers in a small I2C EEPROM at addresses in the 0x50-0x57 range. | | `0x51` | Likely a configuration EEPROM. Many DVB-S receivers store tuner calibration data or device serial numbers in a small I2C EEPROM at addresses in the 0x50-0x57 range. |
The BCM4500's 7-bit I2C address of `0x08` corresponds to 8-bit wire addresses of `0x10` (write) and `0x11` (read). The BCM4500's 7-bit I2C address of `0x08` corresponds to 8-bit wire addresses of `0x10` (write) and `0x11` (read).
## BCM4500 Boot Results After Fix ## BCM4500 Boot Results After Fix
With the `bmSTOP` removed, the full boot sequence completes reliably: With the `bmSTOP` removed, the full boot sequence completes reliably:
- **Boot time:** ~90ms total (30ms power settle + 50ms post-reset delay + ~10ms I2C init) - **Boot time:** ~90ms total (30ms power settle + 50ms post-reset delay + ~10ms I2C init)
- **config_status:** `0x03` (STARTED | FW_LOADED) - **config_status:** `0x03` (STARTED | FW_LOADED)
- **boot_stage:** `0xFF` (COMPLETE) - **boot_stage:** `0xFF` (COMPLETE)
- **Direct registers 0xA2-0xA8:** All return `0x02` (powered, not locked -- expected without a satellite signal) - **Direct registers 0xA2-0xA8:** All return `0x02` (powered, not locked -- expected without a satellite signal)
- **Signal lock:** `0x00` (no lock -- dish not aimed at satellite) - **Signal lock:** `0x00` (no lock -- dish not aimed at satellite)
- **Signal strength:** All zeros (same reason) - **Signal strength:** All zeros (same reason)
- **USB responsiveness:** No hang. The firmware remains fully responsive to vendor commands throughout boot and afterward. - **USB responsiveness:** No hang. The firmware remains fully responsive to vendor commands throughout boot and afterward.
## Firmware v3.01.0 Boot Sequence (Corrected) ## Firmware v3.01.0 Boot Sequence (Corrected)
The complete boot sequence as implemented in `bcm4500_boot()`: The complete boot sequence as implemented in `bcm4500_boot()`:
1. **Assert BCM4500 RESET** -- Drive P0.5 LOW. This holds the BCM4500's digital logic in reset while power is applied. 1. **Assert BCM4500 RESET** -- Drive P0.5 LOW. This holds the BCM4500's digital logic in reset while power is applied.
2. **Power on** -- Set P0.1 HIGH (power enable), P0.2 LOW (power disable off). The SkyWalker-1 has complementary power control pins. 2. **Power on** -- Set P0.1 HIGH (power enable), P0.2 LOW (power disable off). The SkyWalker-1 has complementary power control pins.
3. **delay(30ms)** -- Allow the power supply to settle and reach regulation. The stock firmware uses the same delay. 3. **delay(30ms)** -- Allow the power supply to settle and reach regulation. The stock firmware uses the same delay.
4. **Release RESET** -- Drive P0.5 HIGH. The BCM4500 begins its internal power-on reset (POR) and mask ROM boot sequence. 4. **Release RESET** -- Drive P0.5 HIGH. The BCM4500 begins its internal power-on reset (POR) and mask ROM boot sequence.
5. **delay(50ms)** -- Wait for the BCM4500's POR and internal initialization to complete. The chip needs time for its internal oscillator to stabilize and mask ROM to execute. 5. **delay(50ms)** -- Wait for the BCM4500's POR and internal initialization to complete. The chip needs time for its internal oscillator to stabilize and mask ROM to execute.
6. **I2C probe** -- Read direct register `0xA2` (status) to verify the chip is alive and responding on I2C. If this fails, the boot aborts. 6. **I2C probe** -- Read direct register `0xA2` (status) to verify the chip is alive and responding on I2C. If this fails, the boot aborts.
7. **Write init block 0** -- 7 bytes to BCM4500 indirect page 0, starting at register `0x06`. Written via the `0xA6`/`0xA7`/`0xA8` indirect register protocol. Data: `{0x06, 0x0b, 0x17, 0x38, 0x9f, 0xd9, 0x80}`. 7. **Write init block 0** -- 7 bytes to BCM4500 indirect page 0, starting at register `0x06`. Written via the `0xA6`/`0xA7`/`0xA8` indirect register protocol. Data: `{0x06, 0x0b, 0x17, 0x38, 0x9f, 0xd9, 0x80}`.
8. **Write init block 1** -- 8 bytes to page 0, starting at register `0x07`. Data: `{0x07, 0x09, 0x39, 0x4f, 0x00, 0x65, 0xb7, 0x10}`. 8. **Write init block 1** -- 8 bytes to page 0, starting at register `0x07`. Data: `{0x07, 0x09, 0x39, 0x4f, 0x00, 0x65, 0xb7, 0x10}`.
9. **Write init block 2** -- 3 bytes to page 0, starting at register `0x0F`. Data: `{0x0f, 0x0c, 0x09}`. 9. **Write init block 2** -- 3 bytes to page 0, starting at register `0x0F`. Data: `{0x0f, 0x0c, 0x09}`.
10. **Set config_status** -- OR in `BM_STARTED | BM_FW_LOADED` (`0x03`). Subsequent vendor commands (tuning, signal strength readout, etc.) check this flag before operating. 10. **Set config_status** -- OR in `BM_STARTED | BM_FW_LOADED` (`0x03`). Subsequent vendor commands (tuning, signal strength readout, etc.) check this flag before operating.
The three initialization blocks were extracted from disassembly of the stock v2.06 firmware's `FUN_CODE_0ddd` routine, which performs the same indirect register writes. The three initialization blocks were extracted from disassembly of the stock v2.06 firmware's `FUN_CODE_0ddd` routine, which performs the same indirect register writes.
## FX2 Hardware Recovery Note ## FX2 Hardware Recovery Note
The FX2's CPUCS register at address `0xE600` controls the 8051 CPU's run/halt state. It is accessible via the standard vendor request bRequest=0xA0 (RAM read/write) even when the user firmware is completely hung in an infinite loop. The FX2's CPUCS register at address `0xE600` controls the 8051 CPU's run/halt state. It is accessible via the standard vendor request bRequest=0xA0 (RAM read/write) even when the user firmware is completely hung in an infinite loop.
This works because bRequest=0xA0 is handled by the FX2 silicon's boot ROM, not by firmware. The boot ROM's USB handler runs in a hardware-priority context that preempts the 8051's main loop. Writing `0x01` to CPUCS halts the CPU, new firmware can be loaded into RAM, and writing `0x00` starts it again. This works because bRequest=0xA0 is handled by the FX2 silicon's boot ROM, not by firmware. The boot ROM's USB handler runs in a hardware-priority context that preempts the 8051's main loop. Writing `0x01` to CPUCS halts the CPU, new firmware can be loaded into RAM, and writing `0x00` starts it again.
This means `fw_load.py` can reload firmware over a hung device without requiring a physical USB unplug/replug or power cycle. For iterative firmware development, this is significant -- a failed boot attempt that hangs the firmware can be recovered from the host side in seconds: This means `fw_load.py` can reload firmware over a hung device without requiring a physical USB unplug/replug or power cycle. For iterative firmware development, this is significant -- a failed boot attempt that hangs the firmware can be recovered from the host side in seconds:
```bash ```bash
sudo python3 tools/fw_load.py load firmware/build/skywalker1.ihx --wait 3 sudo python3 tools/fw_load.py load firmware/build/skywalker1.ihx --wait 3
``` ```
The load sequence halts the CPU (CPUCS=0x01), writes new code into RAM, then restarts the CPU (CPUCS=0x00). The device re-enumerates with the new firmware. The load sequence halts the CPU (CPUCS=0x01), writes new code into RAM, then restarts the CPU (CPUCS=0x00). The device re-enumerates with the new firmware.

View File

@ -1,79 +1,79 @@
# DiSEqC for the GenPix Skywalker-1 BDA Driver (Extended) # DiSEqC for the GenPix Skywalker-1 BDA Driver (Extended)
**Implementation Guidelines for Applications** **Implementation Guidelines for Applications**
*Author: Devendra | Created: 2009-07-09 | Source: Microsoft Office Word 2007* *Author: Devendra | Created: 2009-07-09 | Source: Microsoft Office Word 2007*
--- ---
## I. GUID for the SkyWalker1 Extended property ## I. GUID for the SkyWalker1 Extended property
```c ```c
//Used to extend the feature of the BDA //Used to extend the feature of the BDA
//{0B5221EB-F4C4-4976-B959-EF74427464D9} //{0B5221EB-F4C4-4976-B959-EF74427464D9}
#define STATIC_KSPROPSETID_BdaExtendedProperty \ #define STATIC_KSPROPSETID_BdaExtendedProperty \
0x0B5221EB, 0xF4C4, 0x4976, 0xB9, 0x59, 0xEF, 0x74, 0x42, 0x74, 0x64, 0xD9 0x0B5221EB, 0xF4C4, 0x4976, 0xB9, 0x59, 0xEF, 0x74, 0x42, 0x74, 0x64, 0xD9
DEFINE_GUIDSTRUCT("0B5221EB-F4C4-4976-B959-EF74427464D9", KSPROPSETID_BdaExtendedProperty); DEFINE_GUIDSTRUCT("0B5221EB-F4C4-4976-B959-EF74427464D9", KSPROPSETID_BdaExtendedProperty);
#define KSPROPSETID_BdaExtendedProperty DEFINE_GUIDNAMED(KSPROPSETID_BdaExtendedProperty) #define KSPROPSETID_BdaExtendedProperty DEFINE_GUIDNAMED(KSPROPSETID_BdaExtendedProperty)
``` ```
## II. Extended Property List (Only DiSEqC support is extended) ## II. Extended Property List (Only DiSEqC support is extended)
```c ```c
//Extended Property List //Extended Property List
typedef enum __KSPROPERTY_EXTENDED typedef enum __KSPROPERTY_EXTENDED
{ {
/* DiSEqC Command */ /* DiSEqC Command */
//Used to send the Digital Satellite Equipment Control (DiSEqC) //Used to send the Digital Satellite Equipment Control (DiSEqC)
//Commands by application //Commands by application
KSPROPERTY_BDA_DISEQC = 0, //Extension Property 1 KSPROPERTY_BDA_DISEQC = 0, //Extension Property 1
} KSPROPERTY_EXTENDED; } KSPROPERTY_EXTENDED;
``` ```
## III. Enumeration for the Simple Tone Burst ## III. Enumeration for the Simple Tone Burst
```c ```c
typedef enum enSimpleToneBurst typedef enum enSimpleToneBurst
{ {
SEC_MINI_A, SEC_MINI_A,
SEC_MINI_B SEC_MINI_B
} SIMPLE_TONE_BURST; } SIMPLE_TONE_BURST;
``` ```
## IV. DiSEqC Command Structure ## IV. DiSEqC Command Structure
```c ```c
typedef struct __DISEQC_COMMAND typedef struct __DISEQC_COMMAND
{ {
UCHAR ucMessage[MAX_DISEQC_COMMAND_LENGTH]; UCHAR ucMessage[MAX_DISEQC_COMMAND_LENGTH];
/* Byte - 0 : Framing, /* Byte - 0 : Framing,
Byte - 1 : Address, Byte - 1 : Address,
Byte - 2 : Command, Byte - 2 : Command,
Byte - 3 : Data[0], Byte - 3 : Data[0],
Byte - 4 : Data[1], Byte - 4 : Data[1],
Byte - 5 : Data[2] */ Byte - 5 : Data[2] */
UCHAR ucMessageLength; UCHAR ucMessageLength;
/* The Valid values for DiSEqC Command are 3...6 /* The Valid values for DiSEqC Command are 3...6
If this value is 1 then Byte 0 is taken as Simple "Tone Burst" If this value is 1 then Byte 0 is taken as Simple "Tone Burst"
Control Command */ Control Command */
} DISEQC_COMMAND, *PDISEQC_COMMAND; } DISEQC_COMMAND, *PDISEQC_COMMAND;
``` ```
## V. Operation ## V. Operation
### i. To send the Simple Burst command ### i. To send the Simple Burst command
1. Create the `DISEQC_COMMAND` Structure 1. Create the `DISEQC_COMMAND` Structure
2. Set `ucMessage[0]` to either `SEC_MINI_A` or `SEC_MINI_B` 2. Set `ucMessage[0]` to either `SEC_MINI_A` or `SEC_MINI_B`
3. Set `ucMessageLength` as `1` 3. Set `ucMessageLength` as `1`
### ii. To send DiSEqC commands ### ii. To send DiSEqC commands
1. Create the `DISEQC_COMMAND` Structure 1. Create the `DISEQC_COMMAND` Structure
2. Set the Framing value to `ucMessage[0]` (e.g. `0xE0`) 2. Set the Framing value to `ucMessage[0]` (e.g. `0xE0`)
3. Set the Device Address to `ucMessage[1]` (e.g. `0x01`) 3. Set the Device Address to `ucMessage[1]` (e.g. `0x01`)
4. Send the Command for the Device to `ucMessage[2]` 4. Send the Command for the Device to `ucMessage[2]`
5. If required, set the Data bytes `ucMessage[3]`, `ucMessage[4]`, `ucMessage[5]` 5. If required, set the Data bytes `ucMessage[3]`, `ucMessage[4]`, `ucMessage[5]`
6. Set `ucMessageLength` accordingly. Valid values are 3 to 6. 6. Set `ucMessageLength` accordingly. Valid values are 3 to 6.

View File

@ -1,255 +1,255 @@
# DVB-S2 Incompatibility Investigation: Genpix SkyWalker-1 # DVB-S2 Incompatibility Investigation: Genpix SkyWalker-1
## Definitive Conclusion ## Definitive Conclusion
**The SkyWalker-1's inability to receive DVB-S2 is a fundamental hardware limitation of the Broadcom BCM4500 demodulator silicon, not a firmware limitation.** The BCM4500 was designed and fabricated before the DVB-S2 standard was ratified (2005) and contains no LDPC or BCH decoder hardware. DVB-S2 requires LDPC (Low-Density Parity-Check) and BCH (Bose-Chaudhuri-Hocquenghem) forward error correction -- entirely different decoder architectures from the Viterbi/turbo/Reed-Solomon decoders present in the BCM4500. No firmware update could add DVB-S2 support to this hardware. **The SkyWalker-1's inability to receive DVB-S2 is a fundamental hardware limitation of the Broadcom BCM4500 demodulator silicon, not a firmware limitation.** The BCM4500 was designed and fabricated before the DVB-S2 standard was ratified (2005) and contains no LDPC or BCH decoder hardware. DVB-S2 requires LDPC (Low-Density Parity-Check) and BCH (Bose-Chaudhuri-Hocquenghem) forward error correction -- entirely different decoder architectures from the Viterbi/turbo/Reed-Solomon decoders present in the BCM4500. No firmware update could add DVB-S2 support to this hardware.
Genpix eventually addressed this by releasing the SkyWalker-3, which replaced the entire demodulator subsystem (likely switching from Broadcom BCM4500 to STMicroelectronics STV0903), trading turbo-FEC support for DVB-S2 LDPC/BCH capability. Genpix eventually addressed this by releasing the SkyWalker-3, which replaced the entire demodulator subsystem (likely switching from Broadcom BCM4500 to STMicroelectronics STV0903), trading turbo-FEC support for DVB-S2 LDPC/BCH capability.
--- ---
## 1. Does the BCM4500 Silicon Support DVB-S2? ## 1. Does the BCM4500 Silicon Support DVB-S2?
**No. The BCM4500 has no LDPC or BCH decoder hardware.** **No. The BCM4500 has no LDPC or BCH decoder hardware.**
### BCM4500 FEC Architecture (from datasheet) ### BCM4500 FEC Architecture (from datasheet)
The BCM4500 contains exactly two FEC decoder paths: The BCM4500 contains exactly two FEC decoder paths:
1. **Advanced Modulation Turbo FEC Decoder** -- an iterative turbo code decoder supporting: 1. **Advanced Modulation Turbo FEC Decoder** -- an iterative turbo code decoder supporting:
- QPSK: rates 1/4, 1/2, 3/4 - QPSK: rates 1/4, 1/2, 3/4
- 8PSK: rates 2/3, 3/4, 5/6, 8/9 - 8PSK: rates 2/3, 3/4, 5/6, 8/9
- 16QAM: rate 3/4 - 16QAM: rate 3/4
- Reed-Solomon outer code (t=10) after turbo decoding - Reed-Solomon outer code (t=10) after turbo decoding
2. **Legacy DVB/DIRECTV/DCII-Compliant FEC Decoder** -- a concatenated coding chain: 2. **Legacy DVB/DIRECTV/DCII-Compliant FEC Decoder** -- a concatenated coding chain:
- Inner: Viterbi decoder (convolutional code, rates 1/2 through 7/8) - Inner: Viterbi decoder (convolutional code, rates 1/2 through 7/8)
- Outer: Reed-Solomon decoder - Outer: Reed-Solomon decoder
The datasheet describes the signal path explicitly: "Optimized soft decisions are then fed into either a DVB/DIRECTV/DCII-compliant FEC decoder, or an advanced modulation turbo decoder." These are the only two paths. There is no third path for LDPC/BCH. The datasheet describes the signal path explicitly: "Optimized soft decisions are then fed into either a DVB/DIRECTV/DCII-compliant FEC decoder, or an advanced modulation turbo decoder." These are the only two paths. There is no third path for LDPC/BCH.
### DVB-S2 FEC Architecture (for comparison) ### DVB-S2 FEC Architecture (for comparison)
DVB-S2 (EN 302 307, ratified March 2005) mandates: DVB-S2 (EN 302 307, ratified March 2005) mandates:
- **Inner code**: LDPC (Low-Density Parity-Check) -- block lengths of 64,800 or 16,200 bits - **Inner code**: LDPC (Low-Density Parity-Check) -- block lengths of 64,800 or 16,200 bits
- **Outer code**: BCH (Bose-Chaudhuri-Hocquenghem) - **Outer code**: BCH (Bose-Chaudhuri-Hocquenghem)
- **Code rates**: 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5, 5/6, 8/9, 9/10 - **Code rates**: 1/4, 1/3, 2/5, 1/2, 3/5, 2/3, 3/4, 4/5, 5/6, 8/9, 9/10
LDPC decoding requires dedicated hardware: large block RAM for message passing (the LDPC block size is 64,800 bits, requiring significant on-chip storage), iterative belief propagation logic, and a fundamentally different decoder architecture from both Viterbi and turbo decoders. This cannot be emulated in firmware on the BCM4500's simple 8-bit on-chip microcontroller (used only for configuration, acquisition, and monitoring -- not data-path processing). LDPC decoding requires dedicated hardware: large block RAM for message passing (the LDPC block size is 64,800 bits, requiring significant on-chip storage), iterative belief propagation logic, and a fundamentally different decoder architecture from both Viterbi and turbo decoders. This cannot be emulated in firmware on the BCM4500's simple 8-bit on-chip microcontroller (used only for configuration, acquisition, and monitoring -- not data-path processing).
### Evidence from the BCM4500 Datasheet ### Evidence from the BCM4500 Datasheet
Source: [BCM4500 Datasheet (DatasheetQ)](https://html.datasheetq.com/pdf-html/885700/Broadcom/2page/BCM4500.html), [BCM4500 Datasheet (Elcodis)](https://elcodis.com/parts/5786421/BCM4500.html) Source: [BCM4500 Datasheet (DatasheetQ)](https://html.datasheetq.com/pdf-html/885700/Broadcom/2page/BCM4500.html), [BCM4500 Datasheet (Elcodis)](https://elcodis.com/parts/5786421/BCM4500.html)
Key specifications confirming no DVB-S2 capability: Key specifications confirming no DVB-S2 capability:
- Modulation: BPSK, QPSK, 8PSK, 16QAM (no mention of DVB-S2-specific constellations) - Modulation: BPSK, QPSK, 8PSK, 16QAM (no mention of DVB-S2-specific constellations)
- FEC: "advanced modulation turbo FEC decoder" and "DVB/DIRECTV/DCII-compliant FEC decoder" - FEC: "advanced modulation turbo FEC decoder" and "DVB/DIRECTV/DCII-compliant FEC decoder"
- Symbol rate: 256 Ksps to 30 Msps - Symbol rate: 256 Ksps to 30 Msps
- Package: 128-pin MQFP - Package: 128-pin MQFP
- Supply: 3.3V I/O, 1.8V digital - Supply: 3.3V I/O, 1.8V digital
- No mention of LDPC, BCH, or DVB-S2 anywhere in the datasheet - No mention of LDPC, BCH, or DVB-S2 anywhere in the datasheet
--- ---
## 2. What FEC Types Does the BCM4500 Actually Support? ## 2. What FEC Types Does the BCM4500 Actually Support?
The BCM4500 supports three distinct FEC coding families, none of which are DVB-S2 compatible: The BCM4500 supports three distinct FEC coding families, none of which are DVB-S2 compatible:
### 2.1 Viterbi + Reed-Solomon (Legacy DVB-S / DSS / DCII) ### 2.1 Viterbi + Reed-Solomon (Legacy DVB-S / DSS / DCII)
Used for standard DVB-S QPSK, DSS QPSK, DVB-S BPSK, and Digicipher II modes. Used for standard DVB-S QPSK, DSS QPSK, DVB-S BPSK, and Digicipher II modes.
**Firmware evidence** (from `skywalker1-hardware-reference.md`, Section 6.3): **Firmware evidence** (from `skywalker1-hardware-reference.md`, Section 6.3):
- FEC lookup table at XRAM 0xE0F9, maximum index 7 - FEC lookup table at XRAM 0xE0F9, maximum index 7
- Modulation dispatch sets XRAM 0xE0F6 = 0x00 (turbo flag OFF) - Modulation dispatch sets XRAM 0xE0F6 = 0x00 (turbo flag OFF)
- XRAM 0xE0F5 = 0x10 (standard demod mode) - XRAM 0xE0F5 = 0x10 (standard demod mode)
- The firmware FEC table supports rates: 1/2, 2/3, 3/4, 5/6, 7/8, auto, none - The firmware FEC table supports rates: 1/2, 2/3, 3/4, 5/6, 7/8, auto, none
**Windows driver evidence** (`SkyWalker1Control.h`, line 59): **Windows driver evidence** (`SkyWalker1Control.h`, line 59):
```c ```c
m_CurResource.ulInnerFecType = BDA_FEC_VITERBI; m_CurResource.ulInnerFecType = BDA_FEC_VITERBI;
``` ```
**Windows driver evidence** (`SkyWalker1TunerFilter.cpp`, lines 1069-1070): **Windows driver evidence** (`SkyWalker1TunerFilter.cpp`, lines 1069-1070):
```c ```c
//Only supported FEC VITERBI Type Error Correction //Only supported FEC VITERBI Type Error Correction
else if(ulNewInnerFecType == BDA_FEC_VITERBI) else if(ulNewInnerFecType == BDA_FEC_VITERBI)
``` ```
The Windows BDA driver explicitly rejects any FEC type other than `BDA_FEC_VITERBI` and restricts code rates to 1/2, 2/3, 3/4, 5/6, 7/8 (lines 1112-1116). There is no `BDA_FEC_LDPC` handling. The Windows BDA driver explicitly rejects any FEC type other than `BDA_FEC_VITERBI` and restricts code rates to 1/2, 2/3, 3/4, 5/6, 7/8 (lines 1112-1116). There is no `BDA_FEC_LDPC` handling.
### 2.2 Turbo Codes (Proprietary 8PSK/QPSK/16QAM) ### 2.2 Turbo Codes (Proprietary 8PSK/QPSK/16QAM)
Used for Turbo QPSK, Turbo 8PSK, and Turbo 16QAM -- the proprietary "advanced modulation" modes developed by Broadcom for EchoStar/Dish Network. Used for Turbo QPSK, Turbo 8PSK, and Turbo 16QAM -- the proprietary "advanced modulation" modes developed by Broadcom for EchoStar/Dish Network.
**Firmware evidence** (from `tuning-protocol-analysis.md`, Section 3): **Firmware evidence** (from `tuning-protocol-analysis.md`, Section 3):
- Turbo QPSK: FEC table at XRAM 0xE0B7, max index 5 - Turbo QPSK: FEC table at XRAM 0xE0B7, max index 5
- Turbo 8PSK: FEC table at XRAM 0xE0B1, max index 5 - Turbo 8PSK: FEC table at XRAM 0xE0B1, max index 5
- Turbo 16QAM: FEC table at XRAM 0xE0BC, max index 1 - Turbo 16QAM: FEC table at XRAM 0xE0BC, max index 1
- All turbo modes set XRAM 0xE0F6 = 0x01 (turbo flag ON) - All turbo modes set XRAM 0xE0F6 = 0x01 (turbo flag ON)
These turbo codes are proprietary to EchoStar/Broadcom. They are NOT the same as DVB-S2's LDPC codes, despite both being "advanced" coding schemes. The turbo decoder uses a fundamentally different iterative decoding algorithm (parallel concatenated convolutional codes) compared to LDPC (sparse parity-check matrix belief propagation). These turbo codes are proprietary to EchoStar/Broadcom. They are NOT the same as DVB-S2's LDPC codes, despite both being "advanced" coding schemes. The turbo decoder uses a fundamentally different iterative decoding algorithm (parallel concatenated convolutional codes) compared to LDPC (sparse parity-check matrix belief propagation).
### 2.3 Digicipher II (Motorola/GI Proprietary) ### 2.3 Digicipher II (Motorola/GI Proprietary)
Used for DCII combo, split I/Q, and offset QPSK modes. Used for DCII combo, split I/Q, and offset QPSK modes.
**Firmware evidence**: FEC table at XRAM 0xE0BD, max index 9, with a fixed FEC code of 0xFC written to XRAM 0xE0EB. **Firmware evidence**: FEC table at XRAM 0xE0BD, max index 9, with a fixed FEC code of 0xFC written to XRAM 0xE0EB.
### Summary: FEC Architecture Comparison ### Summary: FEC Architecture Comparison
| Feature | BCM4500 (SkyWalker-1) | DVB-S2 Requirement | | Feature | BCM4500 (SkyWalker-1) | DVB-S2 Requirement |
|---------|----------------------|-------------------| |---------|----------------------|-------------------|
| Inner FEC | Viterbi (DVB-S) or Turbo (proprietary) | LDPC | | Inner FEC | Viterbi (DVB-S) or Turbo (proprietary) | LDPC |
| Outer FEC | Reed-Solomon (t=10) | BCH | | Outer FEC | Reed-Solomon (t=10) | BCH |
| Block size | Convolutional (streaming) / Turbo (short blocks) | 64,800 or 16,200 bits | | Block size | Convolutional (streaming) / Turbo (short blocks) | 64,800 or 16,200 bits |
| Decoder type | Trellis-based (Viterbi) or iterative turbo | Iterative belief propagation | | Decoder type | Trellis-based (Viterbi) or iterative turbo | Iterative belief propagation |
| Hardware IP | Hardwired Viterbi + turbo silicon | Requires dedicated LDPC engine | | Hardware IP | Hardwired Viterbi + turbo silicon | Requires dedicated LDPC engine |
| Standardization | DVB-S (ETSI EN 300 421) + proprietary turbo | DVB-S2 (ETSI EN 302 307) | | Standardization | DVB-S (ETSI EN 300 421) + proprietary turbo | DVB-S2 (ETSI EN 302 307) |
--- ---
## 3. What Would a DVB-S2-Capable Replacement Look Like? ## 3. What Would a DVB-S2-Capable Replacement Look Like?
### Broadcom's Own DVB-S2 Chip Timeline ### Broadcom's Own DVB-S2 Chip Timeline
Broadcom addressed DVB-S2 by designing entirely new silicon: Broadcom addressed DVB-S2 by designing entirely new silicon:
| Chip | Year | DVB-S2? | Key Feature | Source | | Chip | Year | DVB-S2? | Key Feature | Source |
|------|------|---------|-------------|--------| |------|------|---------|-------------|--------|
| **BCM4500** | ~2003 | No | Turbo FEC + legacy Viterbi/RS | [Datasheet](https://elcodis.com/parts/5786421/BCM4500.html) | | **BCM4500** | ~2003 | No | Turbo FEC + legacy Viterbi/RS | [Datasheet](https://elcodis.com/parts/5786421/BCM4500.html) |
| **BCM4501** | 2006 | **Yes** | First dual-tuner DVB-S2 receiver; LDPC/BCH decoder | [Broadcom](https://www.broadcom.com/products/broadband/set-top-box/bcm4501), [EDN](https://www.edn.com/bcm4501-dual-dvb-s2-advanced-modulation-satellite-receiver/) | | **BCM4501** | 2006 | **Yes** | First dual-tuner DVB-S2 receiver; LDPC/BCH decoder | [Broadcom](https://www.broadcom.com/products/broadband/set-top-box/bcm4501), [EDN](https://www.edn.com/bcm4501-dual-dvb-s2-advanced-modulation-satellite-receiver/) |
| **BCM4505** | 2007 | **Yes** | Single-channel, 65nm, LDPC/BCH + legacy | [Broadcom](https://www.broadcom.com/products/broadband/set-top-box/bcm4505) | | **BCM4505** | 2007 | **Yes** | Single-channel, 65nm, LDPC/BCH + legacy | [Broadcom](https://www.broadcom.com/products/broadband/set-top-box/bcm4505) |
| **BCM4506** | 2007 | **Yes** | Dual-channel, 65nm, LDPC/BCH + legacy | [Broadcom](https://www.broadcom.com/products/broadband/set-top-box/bcm4506) | | **BCM4506** | 2007 | **Yes** | Dual-channel, 65nm, LDPC/BCH + legacy | [Broadcom](https://www.broadcom.com/products/broadband/set-top-box/bcm4506) |
The BCM4501 datasheet explicitly states it includes "four 8-bit ADCs, all-digital variable rate QPSK/8PSK receivers, advanced modulation LDPC/BCH, and DVB-S-compliant forward error correction decoder." The addition of LDPC/BCH required new silicon -- it was not a firmware upgrade to the BCM4500. The BCM4501 datasheet explicitly states it includes "four 8-bit ADCs, all-digital variable rate QPSK/8PSK receivers, advanced modulation LDPC/BCH, and DVB-S-compliant forward error correction decoder." The addition of LDPC/BCH required new silicon -- it was not a firmware upgrade to the BCM4500.
However, Broadcom restricted sales of these chips to set-top box manufacturers (EchoStar, DIRECTV) and did not sell to PC peripheral makers. This is why Genpix could not simply drop in a BCM4501. However, Broadcom restricted sales of these chips to set-top box manufacturers (EchoStar, DIRECTV) and did not sell to PC peripheral makers. This is why Genpix could not simply drop in a BCM4501.
### What Genpix Actually Did: The SkyWalker-3 ### What Genpix Actually Did: The SkyWalker-3
Genpix released the SkyWalker-3 as a DVB-S2-capable successor, using a completely different demodulator: Genpix released the SkyWalker-3 as a DVB-S2-capable successor, using a completely different demodulator:
| Feature | SkyWalker-1 (BCM4500) | SkyWalker-3 (likely STV0903) | | Feature | SkyWalker-1 (BCM4500) | SkyWalker-3 (likely STV0903) |
|---------|----------------------|---------------------------| |---------|----------------------|---------------------------|
| DVB-S QPSK | Yes | Yes | | DVB-S QPSK | Yes | Yes |
| DVB-S2 QPSK | No | Yes (rates 1/2 through 9/10) | | DVB-S2 QPSK | No | Yes (rates 1/2 through 9/10) |
| DVB-S2 8PSK | No | Yes (rates 3/5 through 9/10) | | DVB-S2 8PSK | No | Yes (rates 3/5 through 9/10) |
| Turbo QPSK | Yes | **No** | | Turbo QPSK | Yes | **No** |
| Turbo 8PSK | Yes | **No** | | Turbo 8PSK | Yes | **No** |
| Turbo 16QAM | Yes | **No** | | Turbo 16QAM | Yes | **No** |
| DCII | Yes | Yes | | DCII | Yes | Yes |
| DSS | Yes | Yes | | DSS | Yes | Yes |
| Symbol rate (DVB-S) | 256 Ksps - 30 Msps | 1 - 45 Msps | | Symbol rate (DVB-S) | 256 Ksps - 30 Msps | 1 - 45 Msps |
| Symbol rate (DVB-S2) | N/A | 5 - 33 Msps | | Symbol rate (DVB-S2) | N/A | 5 - 33 Msps |
| FEC inner (DVB-S) | Viterbi | Viterbi | | FEC inner (DVB-S) | Viterbi | Viterbi |
| FEC inner (DVB-S2) | N/A | LDPC | | FEC inner (DVB-S2) | N/A | LDPC |
| FEC outer (DVB-S2) | N/A | BCH | | FEC outer (DVB-S2) | N/A | BCH |
| Demodulator | Broadcom BCM4500 | STMicroelectronics STV0903 (probable) | | Demodulator | Broadcom BCM4500 | STMicroelectronics STV0903 (probable) |
| Tuner | Broadcom BCM3440 | STMicroelectronics STV6110 (probable) | | Tuner | Broadcom BCM3440 | STMicroelectronics STV6110 (probable) |
Source: [Genpix SkyWalker-3 specifications](https://www.genpix-electronics.com/what-is-skywalker-3.html) Source: [Genpix SkyWalker-3 specifications](https://www.genpix-electronics.com/what-is-skywalker-3.html)
The trade-off is visible: the SkyWalker-3 gained DVB-S2 but lost turbo-FEC support entirely. The turbo codes were proprietary to Broadcom/EchoStar, and the STMicroelectronics STV0903 demodulator does not implement them. This means the SkyWalker-3 cannot receive Dish Network's legacy turbo-coded 8PSK transmissions. The trade-off is visible: the SkyWalker-3 gained DVB-S2 but lost turbo-FEC support entirely. The turbo codes were proprietary to Broadcom/EchoStar, and the STMicroelectronics STV0903 demodulator does not implement them. This means the SkyWalker-3 cannot receive Dish Network's legacy turbo-coded 8PSK transmissions.
--- ---
## 4. Are There Any Hints of DVB-S2 Awareness in the Firmware? ## 4. Are There Any Hints of DVB-S2 Awareness in the Firmware?
**No. There are zero references to DVB-S2, LDPC, or BCH in any firmware version or in the Windows driver source.** **No. There are zero references to DVB-S2, LDPC, or BCH in any firmware version or in the Windows driver source.**
### Firmware Search Results ### Firmware Search Results
Searched all three firmware versions (v2.06, Rev.2 v2.10, v2.13) via Ghidra disassembly and the following source files: Searched all three firmware versions (v2.06, Rev.2 v2.10, v2.13) via Ghidra disassembly and the following source files:
- `SkyWalker1Control.h` -- defines modulation constants 0-9, none related to DVB-S2 - `SkyWalker1Control.h` -- defines modulation constants 0-9, none related to DVB-S2
- `SkyWalker1CommonDef.h` -- device parameter structure uses `BDA_FEC_VITERBI` only - `SkyWalker1CommonDef.h` -- device parameter structure uses `BDA_FEC_VITERBI` only
- `SkyWalker1TunerFilter.cpp` -- explicitly rejects non-QPSK modulation types and non-Viterbi FEC - `SkyWalker1TunerFilter.cpp` -- explicitly rejects non-QPSK modulation types and non-Viterbi FEC
- `SkyWalker1Control.cpp` -- hardcodes `ADV_MOD_DVB_QPSK` (value 0) in tune command byte 8 - `SkyWalker1Control.cpp` -- hardcodes `ADV_MOD_DVB_QPSK` (value 0) in tune command byte 8
**Specific evidence of no DVB-S2 awareness:** **Specific evidence of no DVB-S2 awareness:**
1. **Modulation enum caps at 9** (`SkyWalker1Control.h`, lines 64-74): The modulation constants are `ADV_MOD_DVB_QPSK` (0) through `ADV_MOD_DVB_BPSK` (9). No value 10+ exists for DVB-S2 modes. 1. **Modulation enum caps at 9** (`SkyWalker1Control.h`, lines 64-74): The modulation constants are `ADV_MOD_DVB_QPSK` (0) through `ADV_MOD_DVB_BPSK` (9). No value 10+ exists for DVB-S2 modes.
2. **Firmware dispatch table has exactly 10 entries** (`tuning-protocol-analysis.md`, Section 3.1): The jump table at CODE:0873 contains 20 bytes (10 entries x 2 bytes). Modulation values >= 10 are rejected by the bounds check at CODE:0866. 2. **Firmware dispatch table has exactly 10 entries** (`tuning-protocol-analysis.md`, Section 3.1): The jump table at CODE:0873 contains 20 bytes (10 entries x 2 bytes). Modulation values >= 10 are rejected by the bounds check at CODE:0866.
3. **FEC type is hardcoded to Viterbi** (`SkyWalker1TunerFilter.cpp`, line 1070): `else if(ulNewInnerFecType == BDA_FEC_VITERBI)` -- only Viterbi is accepted; any other FEC type returns `STATUS_INVALID_PARAMETER`. 3. **FEC type is hardcoded to Viterbi** (`SkyWalker1TunerFilter.cpp`, line 1070): `else if(ulNewInnerFecType == BDA_FEC_VITERBI)` -- only Viterbi is accepted; any other FEC type returns `STATUS_INVALID_PARAMETER`.
4. **Tune command hardcodes DVB-S QPSK** (`SkyWalker1Control.cpp`, line 292): `ucCommand[8] = ADV_MOD_DVB_QPSK;` -- the Windows driver always sends modulation type 0 (DVB-S QPSK) regardless of what the application requests. 4. **Tune command hardcodes DVB-S QPSK** (`SkyWalker1Control.cpp`, line 292): `ucCommand[8] = ADV_MOD_DVB_QPSK;` -- the Windows driver always sends modulation type 0 (DVB-S QPSK) regardless of what the application requests.
5. **No LDPC/BCH code rate values** exist in any FEC lookup table. The firmware's XRAM tables at 0xE0B1, 0xE0B7, 0xE0BC, 0xE0BD, and 0xE0F9 contain only Viterbi rates (1/2 through 7/8), turbo rates, and DCII combined codes. 5. **No LDPC/BCH code rate values** exist in any FEC lookup table. The firmware's XRAM tables at 0xE0B1, 0xE0B7, 0xE0BC, 0xE0BD, and 0xE0F9 contain only Viterbi rates (1/2 through 7/8), turbo rates, and DCII combined codes.
6. **No DVB-S2-specific register addresses** appear in the I2C traffic. The BCM4500 is programmed exclusively through indirect registers 0xA6/0xA7/0xA8 with page 0x00 -- a protocol specific to the BCM4500. DVB-S2 demodulators like the STV0903 use entirely different register maps. 6. **No DVB-S2-specific register addresses** appear in the I2C traffic. The BCM4500 is programmed exclusively through indirect registers 0xA6/0xA7/0xA8 with page 0x00 -- a protocol specific to the BCM4500. DVB-S2 demodulators like the STV0903 use entirely different register maps.
--- ---
## 5. Could the GPIF Streaming Path Handle DVB-S2 Data Rates? ## 5. Could the GPIF Streaming Path Handle DVB-S2 Data Rates?
**Yes -- the USB data path is not the bottleneck. The GPIF/USB 2.0 streaming architecture could handle DVB-S2 data rates if the demodulator supported them.** **Yes -- the USB data path is not the bottleneck. The GPIF/USB 2.0 streaming architecture could handle DVB-S2 data rates if the demodulator supported them.**
### Data Rate Analysis ### Data Rate Analysis
**DVB-S2 maximum useful bit rate** (from ETSI EN 302 307): **DVB-S2 maximum useful bit rate** (from ETSI EN 302 307):
- Highest configuration: 8PSK, rate 9/10, 30 Msps = ~72 Mbps raw, ~58 Mbps net after FEC - Highest configuration: 8PSK, rate 9/10, 30 Msps = ~72 Mbps raw, ~58 Mbps net after FEC
- Typical HD transponder: 8PSK, rate 3/4, 27.5 Msps = ~44 Mbps net - Typical HD transponder: 8PSK, rate 3/4, 27.5 Msps = ~44 Mbps net
**GPIF/USB 2.0 throughput capacity:** **GPIF/USB 2.0 throughput capacity:**
- USB 2.0 High Speed bulk: 480 Mbps theoretical, ~35 MB/s (~280 Mbps) practical - USB 2.0 High Speed bulk: 480 Mbps theoretical, ~35 MB/s (~280 Mbps) practical
- GPIF engine: 48 MHz clock, 8-bit data path = 48 MB/s (384 Mbps) theoretical - GPIF engine: 48 MHz clock, 8-bit data path = 48 MB/s (384 Mbps) theoretical
- EP2 FIFO: 4x buffer with AUTOIN, 7 URBs x 8KB on host side - EP2 FIFO: 4x buffer with AUTOIN, 7 URBs x 8KB on host side
**Current DVB-S usage** (from `gpif-streaming-analysis.md`, Section 15): **Current DVB-S usage** (from `gpif-streaming-analysis.md`, Section 15):
- "Transport stream rate: BCM4500 outputs at the satellite symbol rate (up to 30 Msps), but the effective byte rate depends on modulation and coding. USB 2.0 High Speed bulk bandwidth (480 Mbps theoretical, ~35 MB/s practical) is more than sufficient for DVB-S transport streams (typically 1-5 MB/s)." - "Transport stream rate: BCM4500 outputs at the satellite symbol rate (up to 30 Msps), but the effective byte rate depends on modulation and coding. USB 2.0 High Speed bulk bandwidth (480 Mbps theoretical, ~35 MB/s practical) is more than sufficient for DVB-S transport streams (typically 1-5 MB/s)."
**Assessment**: Even at the theoretical maximum DVB-S2 data rate of ~58 Mbps (~7.25 MB/s), the USB 2.0 bulk streaming path has approximately 5x headroom. The GPIF engine configuration (IFCONFIG=0xEE, EP2FIFOCFG=0x0C, FLOWSTATEA with FSEN enabled) is identical across all firmware versions and provides a fully hardware-managed pipeline that would not require modification. **Assessment**: Even at the theoretical maximum DVB-S2 data rate of ~58 Mbps (~7.25 MB/s), the USB 2.0 bulk streaming path has approximately 5x headroom. The GPIF engine configuration (IFCONFIG=0xEE, EP2FIFOCFG=0x0C, FLOWSTATEA with FSEN enabled) is identical across all firmware versions and provides a fully hardware-managed pipeline that would not require modification.
The 8-bit parallel transport stream interface between the demodulator and FX2 is also sufficient -- DVB-S2 uses the same MPEG-TS output format (188-byte packets) as DVB-S. The GPIF waveform and AUTOIN configuration would work unchanged. The 8-bit parallel transport stream interface between the demodulator and FX2 is also sufficient -- DVB-S2 uses the same MPEG-TS output format (188-byte packets) as DVB-S. The GPIF waveform and AUTOIN configuration would work unchanged.
**However**, this is a moot point. The bottleneck is the demodulator silicon, not the data path. Even if you physically replaced the BCM4500 with a DVB-S2-capable chip, you would need to rewrite the entire FX2 firmware (I2C register protocol, tuning sequence, modulation dispatch, FEC configuration) since every DVB-S2 demodulator uses a completely different register interface. **However**, this is a moot point. The bottleneck is the demodulator silicon, not the data path. Even if you physically replaced the BCM4500 with a DVB-S2-capable chip, you would need to rewrite the entire FX2 firmware (I2C register protocol, tuning sequence, modulation dispatch, FEC configuration) since every DVB-S2 demodulator uses a completely different register interface.
--- ---
## Summary ## Summary
| Question | Answer | | Question | Answer |
|----------|--------| |----------|--------|
| Is DVB-S2 a hardware or firmware limitation? | **Hardware** -- the BCM4500 has no LDPC/BCH decoder logic | | Is DVB-S2 a hardware or firmware limitation? | **Hardware** -- the BCM4500 has no LDPC/BCH decoder logic |
| Could a firmware update add DVB-S2? | **No** -- LDPC decoding requires dedicated silicon | | Could a firmware update add DVB-S2? | **No** -- LDPC decoding requires dedicated silicon |
| Which Broadcom chip first added LDPC? | **BCM4501** (2006), followed by BCM4505/BCM4506 (2007) | | Which Broadcom chip first added LDPC? | **BCM4501** (2006), followed by BCM4505/BCM4506 (2007) |
| Any DVB-S2 hints in firmware/driver? | **None** -- zero references to LDPC, BCH, or DVB-S2 | | Any DVB-S2 hints in firmware/driver? | **None** -- zero references to LDPC, BCH, or DVB-S2 |
| Is the USB data path a bottleneck? | **No** -- USB 2.0 bulk has ~5x headroom for DVB-S2 rates | | Is the USB data path a bottleneck? | **No** -- USB 2.0 bulk has ~5x headroom for DVB-S2 rates |
| What did Genpix do for DVB-S2? | Released SkyWalker-3 with a different demodulator (likely STV0903) | | What did Genpix do for DVB-S2? | Released SkyWalker-3 with a different demodulator (likely STV0903) |
| What was lost in the transition? | Turbo-FEC support (proprietary to Broadcom/EchoStar) | | What was lost in the transition? | Turbo-FEC support (proprietary to Broadcom/EchoStar) |
--- ---
## Sources ## Sources
### Datasheets and Product Pages ### Datasheets and Product Pages
- [BCM4500 Datasheet (DatasheetQ)](https://html.datasheetq.com/pdf-html/885700/Broadcom/2page/BCM4500.html) - [BCM4500 Datasheet (DatasheetQ)](https://html.datasheetq.com/pdf-html/885700/Broadcom/2page/BCM4500.html)
- [BCM4500 Datasheet (Elcodis)](https://elcodis.com/parts/5786421/BCM4500.html) - [BCM4500 Datasheet (Elcodis)](https://elcodis.com/parts/5786421/BCM4500.html)
- [BCM4500 Datasheet (AllDatasheet)](https://www.alldatasheet.com/datasheet-pdf/pdf/85246/BOARDCOM/BCM4500.html) - [BCM4500 Datasheet (AllDatasheet)](https://www.alldatasheet.com/datasheet-pdf/pdf/85246/BOARDCOM/BCM4500.html)
- [BCM4501 Product Page (Broadcom)](https://www.broadcom.com/products/broadband/set-top-box/bcm4501) - [BCM4501 Product Page (Broadcom)](https://www.broadcom.com/products/broadband/set-top-box/bcm4501)
- [BCM4501 (EDN)](https://www.edn.com/bcm4501-dual-dvb-s2-advanced-modulation-satellite-receiver/) - [BCM4501 (EDN)](https://www.edn.com/bcm4501-dual-dvb-s2-advanced-modulation-satellite-receiver/)
- [BCM4505 Product Page (Broadcom)](https://www.broadcom.com/products/broadband/set-top-box/bcm4505) - [BCM4505 Product Page (Broadcom)](https://www.broadcom.com/products/broadband/set-top-box/bcm4505)
- [BCM4506 Product Page (Broadcom)](https://www.broadcom.com/products/broadband/set-top-box/bcm4506) - [BCM4506 Product Page (Broadcom)](https://www.broadcom.com/products/broadband/set-top-box/bcm4506)
- [BCM4505/BCM4506 Announcement (RTTNews)](https://www.rttnews.com/380136/broadcom-launches-bcm4505-and-bcm4506-two-fully-integrated-single-chip-single-and-dual-channel-multi-format-satellite-receivers-quick-facts.aspx) - [BCM4505/BCM4506 Announcement (RTTNews)](https://www.rttnews.com/380136/broadcom-launches-bcm4505-and-bcm4506-two-fully-integrated-single-chip-single-and-dual-channel-multi-format-satellite-receivers-quick-facts.aspx)
### Genpix Products ### Genpix Products
- [Genpix SkyWalker-3 Specifications](https://www.genpix-electronics.com/what-is-skywalker-3.html) - [Genpix SkyWalker-3 Specifications](https://www.genpix-electronics.com/what-is-skywalker-3.html)
- [Genpix Official Site](https://www.genpix-electronics.com/index.php?act=viewDoc&docId=9) - [Genpix Official Site](https://www.genpix-electronics.com/index.php?act=viewDoc&docId=9)
### Community and Technical Discussions ### Community and Technical Discussions
- [LinuxTV mailing list: BCM4500 and DVB-S2 distinction](https://www.mail-archive.com/linux-dvb@linuxtv.org/msg24808.html) - [LinuxTV mailing list: BCM4500 and DVB-S2 distinction](https://www.mail-archive.com/linux-dvb@linuxtv.org/msg24808.html)
- [SatelliteGuys: Turbo 8PSK card reverse engineering](https://www.satelliteguys.us/xen/threads/another-turbo-8psk-card.246879/) - [SatelliteGuys: Turbo 8PSK card reverse engineering](https://www.satelliteguys.us/xen/threads/another-turbo-8psk-card.246879/)
- [SatelliteGuys: Genpix SkyWalker-1 discussion](https://www.satelliteguys.us/xen/threads/genpix-skywalker-1.214196/) - [SatelliteGuys: Genpix SkyWalker-1 discussion](https://www.satelliteguys.us/xen/threads/genpix-skywalker-1.214196/)
### Reverse Engineering Analysis (This Project) ### Reverse Engineering Analysis (This Project)
- `skywalker1-hardware-reference.md` -- Sections 1, 6, 7: Overview, tuning protocol, BCM4500 interface - `skywalker1-hardware-reference.md` -- Sections 1, 6, 7: Overview, tuning protocol, BCM4500 interface
- `tuning-protocol-analysis.md` -- Section 3: Modulation dispatch table, FEC lookup tables - `tuning-protocol-analysis.md` -- Section 3: Modulation dispatch table, FEC lookup tables
- `gpif-streaming-analysis.md` -- Sections 13-15: GPIF throughput and data path analysis - `gpif-streaming-analysis.md` -- Sections 13-15: GPIF throughput and data path analysis
- `rev2-deep-analysis.md` -- Complete Rev.2 function inventory - `rev2-deep-analysis.md` -- Complete Rev.2 function inventory
- `SkyWalker1Control.h` -- Modulation mode constants (lines 63-74), FEC/command definitions - `SkyWalker1Control.h` -- Modulation mode constants (lines 63-74), FEC/command definitions
- `SkyWalker1TunerFilter.cpp` -- SetInnerFecType() Viterbi-only restriction (lines 1058-1086) - `SkyWalker1TunerFilter.cpp` -- SetInnerFecType() Viterbi-only restriction (lines 1058-1086)
- `SkyWalker1Control.cpp` -- TuneDevice() hardcoded ADV_MOD_DVB_QPSK (line 292) - `SkyWalker1Control.cpp` -- TuneDevice() hardcoded ADV_MOD_DVB_QPSK (line 292)

File diff suppressed because it is too large Load Diff

View File

@ -1,102 +1,102 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1AntennaPin.h File Name : SkyWalker1AntennaPin.h
Author : Author :
Date : Date :
Purpose : This File Holds the Antenna Pin related declarations Purpose : This File Holds the Antenna Pin related declarations
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef __SKYWALKER1_ANTENNA_PIN_H #ifndef __SKYWALKER1_ANTENNA_PIN_H
#define __SKYWALKER1_ANTENNA_PIN_H #define __SKYWALKER1_ANTENNA_PIN_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1TunerPin.h" #include "SkyWalker1TunerPin.h"
#include "SkyWalker1Extended.h" //For the Extended BDA #include "SkyWalker1Extended.h" //For the Extended BDA
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
//Antenna Pin class. //Antenna Pin class.
class CAntennaPin : public CTunerPin class CAntennaPin : public CTunerPin
{ {
public: public:
static NTSTATUS PinSetDeviceState( static NTSTATUS PinSetDeviceState(
IN PKSPIN Pin, IN PKSPIN Pin,
IN KSSTATE ToState, IN KSSTATE ToState,
IN KSSTATE FromState IN KSSTATE FromState
); );
static NTSTATUS IntersectDataFormat( static NTSTATUS IntersectDataFormat(
IN PVOID pContext, IN PVOID pContext,
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSP_PIN Pin, IN PKSP_PIN Pin,
IN PKSDATARANGE DataRange, IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange, IN PKSDATARANGE MatchingDataRange,
IN ULONG DataBufferSize, IN ULONG DataBufferSize,
OUT PVOID Data OPTIONAL, OUT PVOID Data OPTIONAL,
OUT PULONG DataSize OUT PULONG DataSize
); );
//Network provider and AVStream use these functions //Network provider and AVStream use these functions
//to set and get properties of nodes that are controlled //to set and get properties of nodes that are controlled
//by the input pin. //by the input pin.
static NTSTATUS GetTunerProperty( static NTSTATUS GetTunerProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
); );
static NTSTATUS SetTunerProperty( static NTSTATUS SetTunerProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
); );
//Network provider and AVStream use these functions //Network provider and AVStream use these functions
//to set and get properties of nodes that are controlled //to set and get properties of nodes that are controlled
//by the input pin. //by the input pin.
static NTSTATUS GetTunerLnbProperty( static NTSTATUS GetTunerLnbProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
); );
static NTSTATUS SetTunerLnbProperty( static NTSTATUS SetTunerLnbProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
); );
private: private:
KSSTATE m_KsState; KSSTATE m_KsState;
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*__SKYWALKER1_TRANSPORT_PIN_H*/ #endif /*__SKYWALKER1_TRANSPORT_PIN_H*/

View File

@ -1,72 +1,72 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1CaptureFilter.h File Name : SkyWalker1CaptureFilter.h
Author : Author :
Date : Date :
Purpose : This file contains the filter level header for Purpose : This file contains the filter level header for
the capture filter. the capture filter.
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef SKYWALKER1_CAPTURE_FILTER_H #ifndef SKYWALKER1_CAPTURE_FILTER_H
#define SKYWALKER1_CAPTURE_FILTER_H #define SKYWALKER1_CAPTURE_FILTER_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
//The Capture filter class. //The Capture filter class.
class CCaptureFilter class CCaptureFilter
{ {
public: public:
//The capture filter object constructor. Since the new operator will //The capture filter object constructor. Since the new operator will
//have zeroed the memory, do not bother initializing any NULL or 0 //have zeroed the memory, do not bother initializing any NULL or 0
//fields. Only initialize non-NULL, non-0 fields. //fields. Only initialize non-NULL, non-0 fields.
CCaptureFilter (IN PKSFILTER Filter); CCaptureFilter (IN PKSFILTER Filter);
//The capture filter destructor. //The capture filter destructor.
~CCaptureFilter (); ~CCaptureFilter ();
//This is the filter creation dispatch for the capture filter. It //This is the filter creation dispatch for the capture filter. It
//creates the CCaptureFilter object, associates it with the AVStream //creates the CCaptureFilter object, associates it with the AVStream
//object, and bags it for easy cleanup later. //object, and bags it for easy cleanup later.
static NTSTATUS Create( IN OUT PKSFILTER pKSFilter, static NTSTATUS Create( IN OUT PKSFILTER pKSFilter,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
private: private:
//The AVStream filter object associated with this CCaptureFilter. //The AVStream filter object associated with this CCaptureFilter.
PKSFILTER m_Filter; PKSFILTER m_Filter;
//This is the bag cleanup callback for the CCaptureFilter. Not providing //This is the bag cleanup callback for the CCaptureFilter. Not providing
//one would cause ExFreePool to be used. This is not good for C++ //one would cause ExFreePool to be used. This is not good for C++
//constructed objects. We simply delete the object here. //constructed objects. We simply delete the object here.
static void Cleanup ( IN CCaptureFilter *CapFilter ); static void Cleanup ( IN CCaptureFilter *CapFilter );
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*SKYWALKER1_CAPTURE_FILTER_H*/ #endif /*SKYWALKER1_CAPTURE_FILTER_H*/

View File

@ -1,161 +1,161 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1CapturePin.h File Name : SkyWalker1CapturePin.h
Author : Author :
Date : Date :
Purpose : This file contains header for the video capture pin on the capture Purpose : This file contains header for the video capture pin on the capture
filter. filter.
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
/* Include the Library and Other header file */ /* Include the Library and Other header file */
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
//This Structure can be used in future for the //This Structure can be used in future for the
//better stream management //better stream management
typedef struct _STREAM_POINTER_CONTEXT typedef struct _STREAM_POINTER_CONTEXT
{ {
ULONG ulFrameIndex; ULONG ulFrameIndex;
} STREAM_POINTER_CONTEXT, *PSTREAM_POINTER_CONTEXT; } STREAM_POINTER_CONTEXT, *PSTREAM_POINTER_CONTEXT;
//The video capture pin class. //The video capture pin class.
class CCapturePin : public ICaptureSink class CCapturePin : public ICaptureSink
{ {
private: private:
//The AVStream pin we're associated with. //The AVStream pin we're associated with.
PKSPIN m_Pin; PKSPIN m_Pin;
//Pointer to the internal device object for our capture device. //Pointer to the internal device object for our capture device.
//We access the Device through this object. //We access the Device through this object.
CSkyWalker1Device *m_Device; CSkyWalker1Device *m_Device;
//The state we've put the hardware into. This allows us to keep track //The state we've put the hardware into. This allows us to keep track
//of whether to do things like unpausing or restarting. //of whether to do things like unpausing or restarting.
HARDWARE_STATE m_HardwareState; HARDWARE_STATE m_HardwareState;
//The clock we've been assigned. As with other capture filters, we do //The clock we've been assigned. As with other capture filters, we do
//not expose a clock. If one has been assigned, we will use it to //not expose a clock. If one has been assigned, we will use it to
//time stamp packets (plus a reasonable delta to work the capture stream //time stamp packets (plus a reasonable delta to work the capture stream
//in a preview graph). //in a preview graph).
PIKSREFERENCECLOCK m_Clock; PIKSREFERENCECLOCK m_Clock;
//The transport information for this capture pin. The settings for device will be //The transport information for this capture pin. The settings for device will be
//programmed for this transport info. //programmed for this transport info.
PBDA_TRANSPORT_INFO m_TransportInfo; PBDA_TRANSPORT_INFO m_TransportInfo;
//This Variable is used to keep the count of the Streams sent for the //This Variable is used to keep the count of the Streams sent for the
//Data read //Data read
ULONG m_CurrentFrameIndex; ULONG m_CurrentFrameIndex;
//An indication of whether or not this pin has acquired the necessary //An indication of whether or not this pin has acquired the necessary
//hardware resources to operate. When the pin reaches KSSTATE_ACQUIRE, //hardware resources to operate. When the pin reaches KSSTATE_ACQUIRE,
//we attempt to acquire the hardware. This flag will be set based on //we attempt to acquire the hardware. This flag will be set based on
//our success / failure. //our success / failure.
BOOLEAN m_AcquiredResources; BOOLEAN m_AcquiredResources;
//Clean up any references we hold on frames in the queue. This is called //Clean up any references we hold on frames in the queue. This is called
//when we abruptly stop the fake hardware. //when we abruptly stop the fake hardware.
NTSTATUS CleanupReferences (); NTSTATUS CleanupReferences ();
//This is the state transition handler for the capture pin. It attempts //This is the state transition handler for the capture pin. It attempts
//to acquire resources for the capture pin (or releasing them if //to acquire resources for the capture pin (or releasing them if
//necessary) and starts and stops the hardware as required. //necessary) and starts and stops the hardware as required.
NTSTATUS SetState ( IN KSSTATE ToState,IN KSSTATE FromState); NTSTATUS SetState ( IN KSSTATE ToState,IN KSSTATE FromState);
//This is the processing dispatch for the capture pin. It handles //This is the processing dispatch for the capture pin. It handles
//sending the Streams to the Device. //sending the Streams to the Device.
NTSTATUS Process(); NTSTATUS Process();
//This routine is not required as the Transport Information is already //This routine is not required as the Transport Information is already
//provided into the CCapturePin but still using it to make the //provided into the CCapturePin but still using it to make the
//settings flexible //settings flexible
PBDA_TRANSPORT_INFO CaptureBdaTransportInfo (); PBDA_TRANSPORT_INFO CaptureBdaTransportInfo ();
//This is the free callback from the bagged item (CCapturePin). If we //This is the free callback from the bagged item (CCapturePin). If we
//do not provide a callback when we bag the CCapturePin, ExFreePool //do not provide a callback when we bag the CCapturePin, ExFreePool
//would be called. This is not desirable for C++ constructed objects. //would be called. This is not desirable for C++ constructed objects.
//We merely delete the object here. //We merely delete the object here.
static void Cleanup (IN CCapturePin *Pin) static void Cleanup (IN CCapturePin *Pin)
{ {
delete Pin; delete Pin;
} }
public: public:
//The capture pin's constructor. Initialize any non-0, non-NULL fields //The capture pin's constructor. Initialize any non-0, non-NULL fields
//(since new will have zero'ed the memory anyway) and set up our //(since new will have zero'ed the memory anyway) and set up our
//device level pointers for access during capture routines. //device level pointers for access during capture routines.
CCapturePin (IN PKSPIN Pin); CCapturePin (IN PKSPIN Pin);
//The capture pin's destructor. //The capture pin's destructor.
~CCapturePin (); ~CCapturePin ();
CSkyWalker1Device* GetDevice() CSkyWalker1Device* GetDevice()
{ {
return m_Device; return m_Device;
} }
//This is the capture sink notification mechanism for mapping completion. //This is the capture sink notification mechanism for mapping completion.
//When the device DPC detects that a given number of mappings have been //When the device DPC detects that a given number of mappings have been
//completed by the fake hardware, it signals the capture sink of this //completed by the fake hardware, it signals the capture sink of this
//through this method. //through this method.
virtual void ReleaseStream(IN ULONG ulStreamIndex); virtual void ReleaseStream(IN ULONG ulStreamIndex);
//This is the creation dispatch for the capture pin. It creates //This is the creation dispatch for the capture pin. It creates
//the CCapturePin object and associates it with the AVStream object //the CCapturePin object and associates it with the AVStream object
//bagging it in the process. //bagging it in the process.
static NTSTATUS PinCreate( IN OUT PKSPIN pKSPin, static NTSTATUS PinCreate( IN OUT PKSPIN pKSPin,
IN PIRP pIoRequestPacket IN PIRP pIoRequestPacket
); );
//This is the set device state dispatch for the pin. The routine bridges //This is the set device state dispatch for the pin. The routine bridges
//to SetState() in the context of the CCapturePin. //to SetState() in the context of the CCapturePin.
static NTSTATUS DispatchSetState ( static NTSTATUS DispatchSetState (
IN PKSPIN Pin, IN PKSPIN Pin,
IN KSSTATE ToState, IN KSSTATE ToState,
IN KSSTATE FromState IN KSSTATE FromState
) )
{ {
return return
(reinterpret_cast<CCapturePin *>(Pin->Context))-> (reinterpret_cast<CCapturePin *>(Pin->Context))->
SetState(ToState, FromState); SetState(ToState, FromState);
} }
//This is the processing dispatch for the capture pin. The routine //This is the processing dispatch for the capture pin. The routine
//bridges to Process() in the context of the CCapturePin. //bridges to Process() in the context of the CCapturePin.
static NTSTATUS DispatchProcess (IN PKSPIN Pin) static NTSTATUS DispatchProcess (IN PKSPIN Pin)
{ {
return return
(reinterpret_cast<CCapturePin *>(Pin->Context))->Process(); (reinterpret_cast<CCapturePin *>(Pin->Context))->Process();
} }
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */

View File

@ -1,149 +1,149 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1CommonDef.h File Name : SkyWalker1CommonDef.h
Author : Author :
Date : Date :
Purpose : File to hold the common definitions for the Driver Purpose : File to hold the common definitions for the Driver
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef __SKYWALKER1_COMMON_DEF_H #ifndef __SKYWALKER1_COMMON_DEF_H
#define __SKYWALKER1_COMMON_DEF_H #define __SKYWALKER1_COMMON_DEF_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
#define TUNER_MEM_TAG 'MNUT' #define TUNER_MEM_TAG 'MNUT'
#define CAPTURE_MEM_TAG 'MPAC' #define CAPTURE_MEM_TAG 'MPAC'
// Implementation GUID for SkyWalker1 Tuner and Capture // Implementation GUID for SkyWalker1 Tuner and Capture
// Must match the KSSTRING used in the installation INFs interface sections // Must match the KSSTRING used in the installation INFs interface sections
//Tuner Filter GUID {5C4E764F-AB43-46A9-B21E-8529C70F0A23} //Tuner Filter GUID {5C4E764F-AB43-46A9-B21E-8529C70F0A23}
#define GUID_SKYWALKER_TUNER_FILTER\ #define GUID_SKYWALKER_TUNER_FILTER\
0x5C4E764F, 0xAB43, 0x46A9, 0xB2, 0x1E, 0x85, 0x29, 0xC7, 0x0F, 0x0A, 0x23 0x5C4E764F, 0xAB43, 0x46A9, 0xB2, 0x1E, 0x85, 0x29, 0xC7, 0x0F, 0x0A, 0x23
DEFINE_GUIDSTRUCT("5C4E764F-AB43-46A9-B21E-8529C70F0A23", SKYWALKER_TUNER_FILTER); DEFINE_GUIDSTRUCT("5C4E764F-AB43-46A9-B21E-8529C70F0A23", SKYWALKER_TUNER_FILTER);
#define SKYWALKER_TUNER_FILTER DEFINE_GUIDNAMED(SKYWALKER_TUNER_FILTER) #define SKYWALKER_TUNER_FILTER DEFINE_GUIDNAMED(SKYWALKER_TUNER_FILTER)
//Capture Filter GUID {0F8F74D9-E524-4D05-BB60-F0C69ACB1756} //Capture Filter GUID {0F8F74D9-E524-4D05-BB60-F0C69ACB1756}
#define GUID_SKYWALKER_CAPTURE_FILTER\ #define GUID_SKYWALKER_CAPTURE_FILTER\
0x0F8F74D9, 0xE524, 0x4D05, 0xBB, 0x60, 0xF0, 0xC6, 0x9A, 0xCB, 0x17, 0x56 0x0F8F74D9, 0xE524, 0x4D05, 0xBB, 0x60, 0xF0, 0xC6, 0x9A, 0xCB, 0x17, 0x56
DEFINE_GUIDSTRUCT("0F8F74D9-E524-4D05-BB60-F0C69ACB1756", SKYWALKER_CAPTURE_FILTER); DEFINE_GUIDSTRUCT("0F8F74D9-E524-4D05-BB60-F0C69ACB1756", SKYWALKER_CAPTURE_FILTER);
// Defines the SKYWALKER_CAPTURE_FILTER as a GUID. // Defines the SKYWALKER_CAPTURE_FILTER as a GUID.
#define SKYWALKER_CAPTURE_FILTER DEFINE_GUIDNAMED(SKYWALKER_CAPTURE_FILTER) #define SKYWALKER_CAPTURE_FILTER DEFINE_GUIDNAMED(SKYWALKER_CAPTURE_FILTER)
//Medium GUID {2AEB4A94-FBB7-4FB1-8D74-243B91886EAB} //Medium GUID {2AEB4A94-FBB7-4FB1-8D74-243B91886EAB}
#define GUID_SKYWALKER_TUNER_OUT_MEDIUM\ #define GUID_SKYWALKER_TUNER_OUT_MEDIUM\
0x2AEB4A94, 0xFBB7, 0x4FB1, 0x8D, 0x74, 0x24, 0x3B, 0x91, 0x88, 0x6E, 0xAB 0x2AEB4A94, 0xFBB7, 0x4FB1, 0x8D, 0x74, 0x24, 0x3B, 0x91, 0x88, 0x6E, 0xAB
DEFINE_GUIDSTRUCT("2AEB4A94-FBB7-4FB1-8D74-243B91886EAB", SKYWALKER_TUNER_OUT_MEDIUM); DEFINE_GUIDSTRUCT("2AEB4A94-FBB7-4FB1-8D74-243B91886EAB", SKYWALKER_TUNER_OUT_MEDIUM);
// Defines the SKYWALKER_TUNER_OUT_MEDIUM as a GUID. // Defines the SKYWALKER_TUNER_OUT_MEDIUM as a GUID.
#define SKYWALKER_TUNER_OUT_MEDIUM DEFINE_GUIDNAMED(SKYWALKER_TUNER_OUT_MEDIUM) #define SKYWALKER_TUNER_OUT_MEDIUM DEFINE_GUIDNAMED(SKYWALKER_TUNER_OUT_MEDIUM)
#define TRANSPORT_PACKET_SIZE 128 //188 #define TRANSPORT_PACKET_SIZE 128 //188
#define TRANSPORT_PACKET_COUNT 64 //512 #define TRANSPORT_PACKET_COUNT 64 //512
#define NUMBER_OF_FRAMES 8 #define NUMBER_OF_FRAMES 8
#define PACKET_PER_FRAME 2 #define PACKET_PER_FRAME 2
#define SYMBOL_RATE_MIN 1000 #define SYMBOL_RATE_MIN 1000
#define SYMBOL_RATE_MAX 45000 #define SYMBOL_RATE_MAX 45000
#define TUNER_FREQ_MIN 800000 #define TUNER_FREQ_MIN 800000
#define TUNER_FREQ_MAX 2250000 #define TUNER_FREQ_MAX 2250000
#define IS_VALID(X) (((X)!=NULL)?true:false) #define IS_VALID(X) (((X)!=NULL)?true:false)
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
// Structure for the Tuner Parameters // Structure for the Tuner Parameters
typedef struct _BDATUNER_DEVICE_PARAMETER typedef struct _BDATUNER_DEVICE_PARAMETER
{ {
//Tuner Properties //Tuner Properties
ULONG ulCarrierFrequency; ULONG ulCarrierFrequency;
ULONG ulFrequencyMultiplier; ULONG ulFrequencyMultiplier;
ULONG ulBandWidth; ULONG ulBandWidth;
Polarisation Polarity; Polarisation Polarity;
ULONG ulRange; ULONG ulRange;
ULONG ulTransponder; ULONG ulTransponder;
//LNB Parameters //LNB Parameters
ULONG ulLnbLowLOFrequency; ULONG ulLnbLowLOFrequency;
ULONG ulLnbHighLOFrequency; ULONG ulLnbHighLOFrequency;
ULONG ulLnbSwitchFrequency; ULONG ulLnbSwitchFrequency;
//Demodulator Properties //Demodulator Properties
ULONG ulInnerFecType; ULONG ulInnerFecType;
BinaryConvolutionCodeRate InnerFecRate; BinaryConvolutionCodeRate InnerFecRate;
ULONG ulOuterFecType; ULONG ulOuterFecType;
BinaryConvolutionCodeRate OuterFecRate; BinaryConvolutionCodeRate OuterFecRate;
ModulationType CurrentModulationType; ModulationType CurrentModulationType;
TransmissionMode CurrentTransmissionMode; TransmissionMode CurrentTransmissionMode;
GuardInterval CurrentGuardInterval; GuardInterval CurrentGuardInterval;
SpectralInversion CurrentSpectralInversion; SpectralInversion CurrentSpectralInversion;
ULONG ulSymbolRate; ULONG ulSymbolRate;
} BDATUNER_DEVICE_PARAMETER, * PBDATUNER_DEVICE_PARAMETER; } BDATUNER_DEVICE_PARAMETER, * PBDATUNER_DEVICE_PARAMETER;
// Define a structure that represents the underlying device status. // Define a structure that represents the underlying device status.
// //
typedef struct _BDATUNER_DEVICE_STATUS typedef struct _BDATUNER_DEVICE_STATUS
{ {
//Tuner Status //Tuner Status
DWORD dwSignalStrength; DWORD dwSignalStrength;
DWORD dwSignalQuality; DWORD dwSignalQuality;
BOOLEAN fCarrierPresent; BOOLEAN fCarrierPresent;
//Demodulator Status //Demodulator Status
BOOLEAN fSignalLocked; BOOLEAN fSignalLocked;
} BDATUNER_DEVICE_STATUS, * PBDATUNER_DEVICE_STATUS; } BDATUNER_DEVICE_STATUS, * PBDATUNER_DEVICE_STATUS;
// ICaptureSink: // ICaptureSink:
// //
// This is a capture sink interface. The device level calls back the // This is a capture sink interface. The device level calls back the
// CompleteMappings method passing the number of completed mappings for // CompleteMappings method passing the number of completed mappings for
// the capture pin. This method is called during the device DPC. // the capture pin. This method is called during the device DPC.
class ICaptureSink class ICaptureSink
{ {
public: public:
virtual void ReleaseStream (IN ULONG ulStreamIndex) = 0; virtual void ReleaseStream (IN ULONG ulStreamIndex) = 0;
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
extern const BDA_FILTER_TEMPLATE TunerFilterTemplate; extern const BDA_FILTER_TEMPLATE TunerFilterTemplate;
extern const BDA_FILTER_TEMPLATE SkyWalker1CaptureTemplate; extern const BDA_FILTER_TEMPLATE SkyWalker1CaptureTemplate;
extern const KSFILTER_DESCRIPTOR SkyWalker1TunerFilterDescriptor; extern const KSFILTER_DESCRIPTOR SkyWalker1TunerFilterDescriptor;
extern const KSFILTER_DESCRIPTOR SkyWalker1CaptureFilterDescriptor; extern const KSFILTER_DESCRIPTOR SkyWalker1CaptureFilterDescriptor;
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
typedef enum _HARDWARE_STATE { typedef enum _HARDWARE_STATE {
HardwareStopped = 0, HardwareStopped = 0,
HardwarePaused, HardwarePaused,
HardwareRunning HardwareRunning
} HARDWARE_STATE, *PHARDWARE_STATE; } HARDWARE_STATE, *PHARDWARE_STATE;
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif // __SKYWALKER1_COMMON_DEF_H #endif // __SKYWALKER1_COMMON_DEF_H

View File

@ -1,127 +1,127 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1Control.cpp File Name : SkyWalker1Control.cpp
Author : Author :
Date : Date :
Purpose : This File Holds the Device Control related declarations Purpose : This File Holds the Device Control related declarations
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef __SKYWALKER1_CONTROL_H #ifndef __SKYWALKER1_CONTROL_H
#define __SKYWALKER1_CONTROL_H #define __SKYWALKER1_CONTROL_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* gp8psk commands */ /* gp8psk commands */
/* Twinhan Vendor requests */ /* Twinhan Vendor requests */
#define TH_COMMAND_IN 0xC0 #define TH_COMMAND_IN 0xC0
#define TH_COMMAND_OUT 0xC1 #define TH_COMMAND_OUT 0xC1
/* gp8psk commands */ /* gp8psk commands */
#define GET_8PSK_CONFIG 0x80 /* in */ #define GET_8PSK_CONFIG 0x80 /* in */
#define SET_8PSK_CONFIG 0x81 #define SET_8PSK_CONFIG 0x81
#define I2C_WRITE 0x83 #define I2C_WRITE 0x83
#define I2C_READ 0x84 #define I2C_READ 0x84
#define ARM_TRANSFER 0x85 #define ARM_TRANSFER 0x85
#define TUNE_8PSK 0x86 #define TUNE_8PSK 0x86
#define GET_SIGNAL_STRENGTH 0x87 /* in */ #define GET_SIGNAL_STRENGTH 0x87 /* in */
#define LOAD_BCM4500 0x88 #define LOAD_BCM4500 0x88
#define BOOT_8PSK 0x89 /* in */ #define BOOT_8PSK 0x89 /* in */
#define START_INTERSIL 0x8A /* in */ #define START_INTERSIL 0x8A /* in */
#define SET_LNB_VOLTAGE 0x8B #define SET_LNB_VOLTAGE 0x8B
#define SET_22KHZ_TONE 0x8C #define SET_22KHZ_TONE 0x8C
#define SEND_DISEQC_COMMAND 0x8D #define SEND_DISEQC_COMMAND 0x8D
#define SET_DVB_MODE 0x8E #define SET_DVB_MODE 0x8E
#define SET_DN_SWITCH 0x8F #define SET_DN_SWITCH 0x8F
#define GET_SIGNAL_LOCK 0x90 /* in */ #define GET_SIGNAL_LOCK 0x90 /* in */
#define GET_SERIAL_NUMBER 0x93 /* in */ #define GET_SERIAL_NUMBER 0x93 /* in */
#define USE_EXTRA_VOLT 0x94 #define USE_EXTRA_VOLT 0x94
#define CW3K_INIT 0x9d #define CW3K_INIT 0x9d
/* PSK_configuration bits */ /* PSK_configuration bits */
#define bm8pskStarted 0x01 #define bm8pskStarted 0x01
#define bm8pskFW_Loaded 0x02 #define bm8pskFW_Loaded 0x02
#define bmIntersilOn 0x04 #define bmIntersilOn 0x04
#define bmDVBmode 0x08 #define bmDVBmode 0x08
#define bm22kHz 0x10 #define bm22kHz 0x10
#define bmSEL18V 0x20 #define bmSEL18V 0x20
#define bmDCtuned 0x40 #define bmDCtuned 0x40
#define bmArmed 0x80 #define bmArmed 0x80
/* Satellite modulation modes */ /* Satellite modulation modes */
#define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */ #define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */
#define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */ #define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */
#define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */ #define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */
#define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */ #define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */
#define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */ #define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */
#define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */ #define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */
#define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */ #define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */
#define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */ #define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */
#define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */ #define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */
#define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */ #define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */
#define GET_USB_SPEED 0x07 #define GET_USB_SPEED 0x07
#define USB_SPEED_LOW 0 #define USB_SPEED_LOW 0
#define USB_SPEED_FULL 1 #define USB_SPEED_FULL 1
#define USB_SPEED_HIGH 2 #define USB_SPEED_HIGH 2
#define RESET_FX2 0x13 #define RESET_FX2 0x13
#define FW_VERSION_READ 0x0B #define FW_VERSION_READ 0x0B
#define VENDOR_STRING_READ 0x0C #define VENDOR_STRING_READ 0x0C
#define PRODUCT_STRING_READ 0x0D #define PRODUCT_STRING_READ 0x0D
#define FW_BCD_VERSION_READ 0x14 #define FW_BCD_VERSION_READ 0x14
#define SEC_VOLTAGE_13 0 #define SEC_VOLTAGE_13 0
#define SEC_VOLTAGE_18 1 #define SEC_VOLTAGE_18 1
#define SEC_TONE_ON 0 #define SEC_TONE_ON 0
#define SEC_TONE_OFF 1 #define SEC_TONE_OFF 1
#define SWITCH_ON_TUNER 1 #define SWITCH_ON_TUNER 1
#define SWITCH_OFF_TUNER 0 #define SWITCH_OFF_TUNER 0
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
NTSTATUS GetSignalStatus( IN PKSDEVICE pKSDeviceObject, NTSTATUS GetSignalStatus( IN PKSDEVICE pKSDeviceObject,
OUT PBOOLEAN pbSignalLockStatus OUT PBOOLEAN pbSignalLockStatus
); );
NTSTATUS ReadTunerSignalStrength( IN PKSDEVICE pKSDeviceObject, NTSTATUS ReadTunerSignalStrength( IN PKSDEVICE pKSDeviceObject,
OUT PULONG pulSigStrength OUT PULONG pulSigStrength
); );
NTSTATUS SetLnbVoltage(IN PKSDEVICE pKSDeviceObject, NTSTATUS SetLnbVoltage(IN PKSDEVICE pKSDeviceObject,
IN UCHAR ucVoltage); IN UCHAR ucVoltage);
NTSTATUS TuneDevice(IN PKSDEVICE pKSDeviceObject, NTSTATUS TuneDevice(IN PKSDEVICE pKSDeviceObject,
IN PBDATUNER_DEVICE_PARAMETER pDeviceParameter); IN PBDATUNER_DEVICE_PARAMETER pDeviceParameter);
NTSTATUS SetupTunerPower( IN PKSDEVICE pKSDeviceObject, NTSTATUS SetupTunerPower( IN PKSDEVICE pKSDeviceObject,
IN BOOLEAN bOnOff); IN BOOLEAN bOnOff);
NTSTATUS SetStreamingControl( IN PKSDEVICE pKSDeviceObject, NTSTATUS SetStreamingControl( IN PKSDEVICE pKSDeviceObject,
IN UCHAR ucOnOff); IN UCHAR ucOnOff);
NTSTATUS SetTunerTone( IN PKSDEVICE pKSDeviceObject, NTSTATUS SetTunerTone( IN PKSDEVICE pKSDeviceObject,
IN UCHAR ucTone); IN UCHAR ucTone);
NTSTATUS ConfigureTuner(IN PKSDEVICE pKSDeviceObject, NTSTATUS ConfigureTuner(IN PKSDEVICE pKSDeviceObject,
IN PBDATUNER_DEVICE_PARAMETER pNewConfiguration); IN PBDATUNER_DEVICE_PARAMETER pNewConfiguration);
NTSTATUS DiseqcCommand( IN PKSDEVICE pKSDeviceObject, NTSTATUS DiseqcCommand( IN PKSDEVICE pKSDeviceObject,
IN PDISEQC_COMMAND pCommand); IN PDISEQC_COMMAND pCommand);
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*__SKYWALKER1_CONTROL_H*/ #endif /*__SKYWALKER1_CONTROL_H*/

View File

@ -1,187 +1,187 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1Device.h File Name : SkyWalker1Device.h
Author : Author :
Date : Date :
Purpose : Main Skywalker Device level Implementation Purpose : Main Skywalker Device level Implementation
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
01 Initial Version 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef SKYWALKER1_TUNER_DEVICE_H #ifndef SKYWALKER1_TUNER_DEVICE_H
#define SKYWALKER1_TUNER_DEVICE_H #define SKYWALKER1_TUNER_DEVICE_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1USB.h" #include "SkyWalker1USB.h"
#include "SkyWalker1Extended.h" #include "SkyWalker1Extended.h"
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
//The SkyWalker1 Device class. //The SkyWalker1 Device class.
class CSkyWalker1Device class CSkyWalker1Device
{ {
public: public:
//Device Initialization and Dispatch Related definitions //Device Initialization and Dispatch Related definitions
NTSTATUS Create(IN PKSDEVICE pKSDeviceObject); NTSTATUS Create(IN PKSDEVICE pKSDeviceObject);
NTSTATUS Start( NTSTATUS Start(
IN PKSDEVICE pKSDeviceObject, IN PKSDEVICE pKSDeviceObject,
IN PIRP pIrp, IN PIRP pIrp,
IN PCM_RESOURCE_LIST pResourceList OPTIONAL, IN PCM_RESOURCE_LIST pResourceList OPTIONAL,
IN PCM_RESOURCE_LIST pTranslatedResourceList OPTIONAL IN PCM_RESOURCE_LIST pTranslatedResourceList OPTIONAL
); );
NTSTATUS Stop( IN PKSDEVICE pKSDeviceObject, NTSTATUS Stop( IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS Close( IN PKSDEVICE pKSDeviceObject, NTSTATUS Close( IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS SetPower( NTSTATUS SetPower(
IN PKSDEVICE pKSDeviceObject, //Pointer to the device object IN PKSDEVICE pKSDeviceObject, //Pointer to the device object
//provided by the system. //provided by the system.
IN PIRP pIoRequestPacket,//Pointer to the IRP related to this request. IN PIRP pIoRequestPacket,//Pointer to the IRP related to this request.
IN DEVICE_POWER_STATE To, //Requested power state. IN DEVICE_POWER_STATE To, //Requested power state.
IN DEVICE_POWER_STATE From //Current power state. IN DEVICE_POWER_STATE From //Current power state.
); );
NTSTATUS InitializeTuner( IN PKSDEVICE pKSDeviceObject, NTSTATUS InitializeTuner( IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
// Device access related Function definitions // Device access related Function definitions
// An instance of the filter uses these functions // An instance of the filter uses these functions
// to manage resources on the device. // to manage resources on the device.
NTSTATUS Acquire(IN PBDATUNER_DEVICE_PARAMETER pNewResource, NTSTATUS Acquire(IN PBDATUNER_DEVICE_PARAMETER pNewResource,
OUT PULONG pulAcquiredResourceID); OUT PULONG pulAcquiredResourceID);
NTSTATUS Update( IN PBDATUNER_DEVICE_PARAMETER pNewResource, NTSTATUS Update( IN PBDATUNER_DEVICE_PARAMETER pNewResource,
IN ULONG ulResourceID); IN ULONG ulResourceID);
NTSTATUS SendDiseqcCommand( NTSTATUS SendDiseqcCommand(
IN PDISEQC_COMMAND pDiseqcCommand, IN PDISEQC_COMMAND pDiseqcCommand,
IN ULONG ulResourceID IN ULONG ulResourceID
); );
NTSTATUS Release(IN ULONG ulResourceID); NTSTATUS Release(IN ULONG ulResourceID);
NTSTATUS GetStatus(PBDATUNER_DEVICE_STATUS pDeviceStatus); NTSTATUS GetStatus(PBDATUNER_DEVICE_STATUS pDeviceStatus);
//DMA Adapter related Functions //DMA Adapter related Functions
NTSTATUS InitializeAdapterStream(IN PKSDEVICE pKSDeviceObject); NTSTATUS InitializeAdapterStream(IN PKSDEVICE pKSDeviceObject);
//Stream Capture Related Fuctions //Stream Capture Related Fuctions
NTSTATUS SetupCaptureSink ( NTSTATUS SetupCaptureSink (
IN ICaptureSink * pCapturePin, IN ICaptureSink * pCapturePin,
IN PBDA_TRANSPORT_INFO TransportInfo IN PBDA_TRANSPORT_INFO TransportInfo
); );
void RemoveCaptureSink (); void RemoveCaptureSink ();
NTSTATUS StartStream (); NTSTATUS StartStream ();
NTSTATUS PauseStream (IN BOOLEAN Pausing); NTSTATUS PauseStream (IN BOOLEAN Pausing);
NTSTATUS StopStream (); NTSTATUS StopStream ();
NTSTATUS ReadStream(IN ULONG ulStreamIndex); NTSTATUS ReadStream(IN ULONG ulStreamIndex);
void ProcessStream(IN ULONG ulStreamIndex); void ProcessStream(IN ULONG ulStreamIndex);
BOOLEAN TimeToReadSignalStatus(void); BOOLEAN TimeToReadSignalStatus(void);
PKSDEVICE m_pKSDevice; PKSDEVICE m_pKSDevice;
//USB Related definitions //USB Related definitions
USB_DEVICE_DESCRIPTOR USBDeviceDescriptor; USB_DEVICE_DESCRIPTOR USBDeviceDescriptor;
USBD_PIPE_INFORMATION ReadPipe; USBD_PIPE_INFORMATION ReadPipe;
USBD_PIPE_INFORMATION WritePipe; USBD_PIPE_INFORMATION WritePipe;
USBSTATE UsbDeviceState; USBSTATE UsbDeviceState;
USBSTATE PreviousUsbDeviceState; USBSTATE PreviousUsbDeviceState;
//Pending I/O queue state //Pending I/O queue state
QUEUE_STATE QueueState; QUEUE_STATE QueueState;
//obtain and hold this lock while changing the device state, //obtain and hold this lock while changing the device state,
//the queue state and while processing the queue. //the queue state and while processing the queue.
KSPIN_LOCK DeviceStateLock; KSPIN_LOCK DeviceStateLock;
//Current Usb Irp //Current Usb Irp
PIRP pUsbStreamIrp[PACKET_PER_FRAME * NUMBER_OF_FRAMES]; PIRP pUsbStreamIrp[PACKET_PER_FRAME * NUMBER_OF_FRAMES];
//Device Stop Event //Device Stop Event
KEVENT EvDeviceStopOk; KEVENT EvDeviceStopOk;
//Device Remove Event //Device Remove Event
KEVENT EvDeviceRemoveOk; KEVENT EvDeviceRemoveOk;
//Outstanding IO Count for the Driver //Outstanding IO Count for the Driver
ULONG ulOutStandingIoCount; ULONG ulOutStandingIoCount;
//Outstanding IO Count Lock //Outstanding IO Count Lock
KSPIN_LOCK kIoCountLock; KSPIN_LOCK kIoCountLock;
PDMA_ADAPTER m_pDMAAdapter; PDMA_ADAPTER m_pDMAAdapter;
ULONG m_SampleSize; ULONG m_SampleSize;
//Temporary Bytes Read Counter //Temporary Bytes Read Counter
ULONG m_NumberOfBytesRead[NUMBER_OF_FRAMES]; ULONG m_NumberOfBytesRead[NUMBER_OF_FRAMES];
PUCHAR GetSynthBuffer(ULONG ulStreamIndex) PUCHAR GetSynthBuffer(ULONG ulStreamIndex)
{ {
return m_SynthesisBuffer[ulStreamIndex]; return m_SynthesisBuffer[ulStreamIndex];
} }
private: private:
ULONG m_ulDeviceInstance; ULONG m_ulDeviceInstance;
BDATUNER_DEVICE_PARAMETER m_CurResource; BDATUNER_DEVICE_PARAMETER m_CurResource;
BDATUNER_DEVICE_STATUS m_TunerStatus; BDATUNER_DEVICE_STATUS m_TunerStatus;
ULONG m_ulCurResourceID; ULONG m_ulCurResourceID;
ULONG m_ulcResourceUsers; ULONG m_ulcResourceUsers;
LARGE_INTEGER m_PreviousStatusReadTime; LARGE_INTEGER m_PreviousStatusReadTime;
//The synthesis buffer. This is a private buffer we use to store the //The synthesis buffer. This is a private buffer we use to store the
//references of the Streaming Data.It is used for the Reading data //references of the Streaming Data.It is used for the Reading data
//from the device and also Copying Data to the Stream Buffer sent //from the device and also Copying Data to the Stream Buffer sent
//by the application //by the application
PUCHAR m_SynthesisBuffer[NUMBER_OF_FRAMES]; PUCHAR m_SynthesisBuffer[NUMBER_OF_FRAMES];
//Key information regarding the frames we generate. //Key information regarding the frames we generate.
LONGLONG m_TimePerFrame; LONGLONG m_TimePerFrame;
ULONG m_PacketSize; ULONG m_PacketSize;
ULONG m_PacketsPerSample; ULONG m_PacketsPerSample;
//The current state of the Device //The current state of the Device
HARDWARE_STATE m_HardwareState; HARDWARE_STATE m_HardwareState;
//The pause / stop hardware flag and event. //The pause / stop hardware flag and event.
BOOLEAN m_StopHardware; BOOLEAN m_StopHardware;
KEVENT m_HardwareEvent; KEVENT m_HardwareEvent;
//Number of pins with resources acquired. This is used as a locking //Number of pins with resources acquired. This is used as a locking
//mechanism for resource acquisition on the device. //mechanism for resource acquisition on the device.
LONG m_PinsWithResources; LONG m_PinsWithResources;
//The capture sink. When we complete stream reading, we //The capture sink. When we complete stream reading, we
//notify the capture sink. //notify the capture sink.
ICaptureSink *m_CaptureSink; ICaptureSink *m_CaptureSink;
//The video info header we're basing hardware settings on. The pin //The video info header we're basing hardware settings on. The pin
//provides this to us when acquiring resources and must guarantee its //provides this to us when acquiring resources and must guarantee its
//stability until resources are released. //stability until resources are released.
PBDA_TRANSPORT_INFO m_TransportInfo; PBDA_TRANSPORT_INFO m_TransportInfo;
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*SKYWALKER1_TUNER_DEVICE_H*/ #endif /*SKYWALKER1_TUNER_DEVICE_H*/

View File

@ -1,109 +1,109 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1AntennaPin.h File Name : SkyWalker1AntennaPin.h
Author : Author :
Date : Date :
Purpose : This File Holds the Extended BDA Definitions Purpose : This File Holds the Extended BDA Definitions
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef __SKYWALKER1_EXTENDED_H #ifndef __SKYWALKER1_EXTENDED_H
#define __SKYWALKER1_EXTENDED_H #define __SKYWALKER1_EXTENDED_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#if !defined(_KSMEDIA_) #if !defined(_KSMEDIA_)
#error KSMEDIA.H must be included before BDAMEDIA.H #error KSMEDIA.H must be included before BDAMEDIA.H
#endif // !defined(_KSMEDIA_) #endif // !defined(_KSMEDIA_)
#if !defined(_BDATYPES_) #if !defined(_BDATYPES_)
#error BDATYPES.H must be included before BDAMEDIA.H #error BDATYPES.H must be included before BDAMEDIA.H
#endif // !defined(_BDATYPES_) #endif // !defined(_BDATYPES_)
#if !defined(_BDAMEDIA_) #if !defined(_BDAMEDIA_)
#define _BDAMEDIA_ #define _BDAMEDIA_
#endif // !defined(_BDAMEDIA_) #endif // !defined(_BDAMEDIA_)
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
#define MAX_DISEQC_COMMAND_LENGTH 6 #define MAX_DISEQC_COMMAND_LENGTH 6
/* Extended Property*/ /* Extended Property*/
//Used to extend the feature of the BDA //Used to extend the feature of the BDA
//{0B5221EB-F4C4-4976-B959-EF74427464D9} //{0B5221EB-F4C4-4976-B959-EF74427464D9}
#define STATIC_KSPROPSETID_BdaExtendedProperty \ #define STATIC_KSPROPSETID_BdaExtendedProperty \
0x0B5221EB, 0xF4C4, 0x4976, 0xB9, 0x59, 0xEF, 0x74, 0x42, 0x74, 0x64, 0xD9 0x0B5221EB, 0xF4C4, 0x4976, 0xB9, 0x59, 0xEF, 0x74, 0x42, 0x74, 0x64, 0xD9
DEFINE_GUIDSTRUCT("0B5221EB-F4C4-4976-B959-EF74427464D9", KSPROPSETID_BdaExtendedProperty); DEFINE_GUIDSTRUCT("0B5221EB-F4C4-4976-B959-EF74427464D9", KSPROPSETID_BdaExtendedProperty);
#define KSPROPSETID_BdaExtendedProperty DEFINE_GUIDNAMED(KSPROPSETID_BdaExtendedProperty) #define KSPROPSETID_BdaExtendedProperty DEFINE_GUIDNAMED(KSPROPSETID_BdaExtendedProperty)
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Declare Enumerations here */ /* Declare Enumerations here */
//Extended Property List //Extended Property List
typedef enum __KSPROPERTY_EXTENDED typedef enum __KSPROPERTY_EXTENDED
{ {
/* DiSEqC Command */ /* DiSEqC Command */
//Used to send the Digital Sattelite Equipment Control (DiSEqC) //Used to send the Digital Sattelite Equipment Control (DiSEqC)
//Commands by application //Commands by application
KSPROPERTY_BDA_DISEQC = 0, //Extension Property 1 KSPROPERTY_BDA_DISEQC = 0, //Extension Property 1
//Add New Extended Commands Here //Add New Extended Commands Here
}KSPROPERTY_EXTENDED; }KSPROPERTY_EXTENDED;
//Enumeration can be used during Simple Tone Burst Command //Enumeration can be used during Simple Tone Burst Command
typedef enum enSimpleToneBurst typedef enum enSimpleToneBurst
{ {
SEC_MINI_A, SEC_MINI_A,
SEC_MINI_B SEC_MINI_B
}SIMPLE_TONE_BURST; }SIMPLE_TONE_BURST;
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
//DiSEqC Command related Structure definitions //DiSEqC Command related Structure definitions
typedef struct __DISEQC_COMMAND typedef struct __DISEQC_COMMAND
{ {
UCHAR ucMessage[MAX_DISEQC_COMMAND_LENGTH]; /* UCHAR ucMessage[MAX_DISEQC_COMMAND_LENGTH]; /*
Byte - 0 : Framing, Byte - 0 : Framing,
Byte - 1 : Address, Byte - 1 : Address,
Byte - 2 : Command, Byte - 2 : Command,
Byte - 3 : Data[0], Byte - 3 : Data[0],
Byte - 4 : Data[1], Byte - 4 : Data[1],
Byte - 5 : Data[2] Byte - 5 : Data[2]
*/ */
UCHAR ucMessageLength;/* The Valid values for DiSEqC Command are 3...6 UCHAR ucMessageLength;/* The Valid values for DiSEqC Command are 3...6
If this value is 1 then the Byte 0 is taken as Simple "Tone Burst" Control If this value is 1 then the Byte 0 is taken as Simple "Tone Burst" Control
Command */ Command */
}DISEQC_COMMAND,*PDISEQC_COMMAND; }DISEQC_COMMAND,*PDISEQC_COMMAND;
//Property that will be used to send the Diseqc command by the application //Property that will be used to send the Diseqc command by the application
#define DEFINE_KSPROPERTY_ITEM_BDA_DISEQC(GetHandler, SetHandler)\ #define DEFINE_KSPROPERTY_ITEM_BDA_DISEQC(GetHandler, SetHandler)\
DEFINE_KSPROPERTY_ITEM(\ DEFINE_KSPROPERTY_ITEM(\
KSPROPERTY_BDA_DISEQC,\ KSPROPERTY_BDA_DISEQC,\
(GetHandler),\ (GetHandler),\
sizeof(KSP_NODE),\ sizeof(KSP_NODE),\
sizeof(DISEQC_COMMAND),\ sizeof(DISEQC_COMMAND),\
(SetHandler),\ (SetHandler),\
NULL, 0, NULL, NULL, 0) NULL, 0, NULL, NULL, 0)
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*__SKYWALKER1_EXTENDED_H*/ #endif /*__SKYWALKER1_EXTENDED_H*/

View File

@ -1,69 +1,69 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1Main.h File Name : SkyWalker1Main.h
Author : Author :
Date : Date :
Purpose : Entry point for the Driver Purpose : Entry point for the Driver
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef __SKYWALKER1_MAIN_H #ifndef __SKYWALKER1_MAIN_H
#define __SKYWALKER1_MAIN_H #define __SKYWALKER1_MAIN_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include <winerror.h> #include <winerror.h>
#include <unknown.h> #include <unknown.h>
#include <ks.h> //Kernel Streaming Driver #include <ks.h> //Kernel Streaming Driver
#include <ksmedia.h> #include <ksmedia.h>
#include <bdatypes.h> #include <bdatypes.h>
#include <bdamedia.h> #include <bdamedia.h>
#include <atsmedia.h> #include <atsmedia.h>
#include <bdasup.h> #include <bdasup.h>
#include <kcom.h> #include <kcom.h>
#include <ksdebug.h> #include <ksdebug.h>
#include "SkyWalker1AntennaPin.h" #include "SkyWalker1AntennaPin.h"
#include "SkyWalker1CaptureFilter.h" #include "SkyWalker1CaptureFilter.h"
#include "SkyWalker1CapturePin.h" #include "SkyWalker1CapturePin.h"
#include "SkyWalker1CommonDef.h" #include "SkyWalker1CommonDef.h"
#include "SkyWalker1Control.h" #include "SkyWalker1Control.h"
#include "SkyWalker1Device.h" #include "SkyWalker1Device.h"
#include "SkyWalker1TransportPin.h" #include "SkyWalker1TransportPin.h"
#include "SkyWalker1TunerFilter.h" #include "SkyWalker1TunerFilter.h"
#include "SkyWalker1TunerPin.h" #include "SkyWalker1TunerPin.h"
#include "SkyWalker1Extended.h" #include "SkyWalker1Extended.h"
extern "C" extern "C"
{ {
#include <wdm.h> //For the Mutex #include <wdm.h> //For the Mutex
#include <wchar.h> //For the WCHAR and swprintf #include <wchar.h> //For the WCHAR and swprintf
#include <stdio.h> //For sprintf() function #include <stdio.h> //For sprintf() function
#include "SkyWalker1PnP.h" //Header for the PnP related definitions #include "SkyWalker1PnP.h" //Header for the PnP related definitions
#include "SkyWalker1USB.h" #include "SkyWalker1USB.h"
#include "SkyWalker1Utility.h" #include "SkyWalker1Utility.h"
} }
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*__SKYWALKER1_MAIN_H*/ #endif /*__SKYWALKER1_MAIN_H*/

View File

@ -1,56 +1,56 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1PnP.h File Name : SkyWalker1PnP.h
Author : Author :
Date : Date :
Purpose : PnP IRP Message Handler Purpose : PnP IRP Message Handler
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef __SKYWALKER1_PNP_H #ifndef __SKYWALKER1_PNP_H
#define __SKYWALKER1_PNP_H #define __SKYWALKER1_PNP_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
NTSTATUS SkyWalker1AddDevice(IN PKSDEVICE pKSDeviceObject); NTSTATUS SkyWalker1AddDevice(IN PKSDEVICE pKSDeviceObject);
VOID SkyWalker1Remove( IN PKSDEVICE pKSDeviceObject, VOID SkyWalker1Remove( IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS SkyWalker1Start(IN PKSDEVICE pKSDeviceObject, NTSTATUS SkyWalker1Start(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PCM_RESOURCE_LIST pResourceList, IN PCM_RESOURCE_LIST pResourceList,
IN PCM_RESOURCE_LIST pCIResourceListTranslated); IN PCM_RESOURCE_LIST pCIResourceListTranslated);
VOID SkyWalker1Stop(IN PKSDEVICE pKSDeviceObject, VOID SkyWalker1Stop(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS SkyWalker1QueryStop( IN PKSDEVICE pKSDeviceObject, NTSTATUS SkyWalker1QueryStop( IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
VOID SkyWalker1SetPower VOID SkyWalker1SetPower
( (
IN PKSDEVICE pKSDeviceObject, //Pointer to the device object IN PKSDEVICE pKSDeviceObject, //Pointer to the device object
//provided by the system. //provided by the system.
IN PIRP pIoRequestPacket, //Pointer to the IRP related to this request. IN PIRP pIoRequestPacket, //Pointer to the IRP related to this request.
IN DEVICE_POWER_STATE To, //Requested power state. IN DEVICE_POWER_STATE To, //Requested power state.
IN DEVICE_POWER_STATE From //Current power state. IN DEVICE_POWER_STATE From //Current power state.
); );
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif // __SKYWALKER1_PNP_H #endif // __SKYWALKER1_PNP_H

View File

@ -1,84 +1,84 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1TransportPin.h File Name : SkyWalker1TransportPin.h
Author : Author :
Date : Date :
Purpose : This file contains header for the Transport pin on the Tuner Purpose : This file contains header for the Transport pin on the Tuner
filter. filter.
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef __SKYWALKER1_TRANSPORT_PIN_H #ifndef __SKYWALKER1_TRANSPORT_PIN_H
#define __SKYWALKER1_TRANSPORT_PIN_H #define __SKYWALKER1_TRANSPORT_PIN_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
//#include "SkyWalker1CommonDef.h" //#include "SkyWalker1CommonDef.h"
#include "SkyWalker1TunerPin.h" #include "SkyWalker1TunerPin.h"
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
//The Trasport Pin class. //The Trasport Pin class.
class CTransportPin : public CTunerPin class CTransportPin : public CTunerPin
{ {
public: public:
//Define a data intersection handler function for the //Define a data intersection handler function for the
//pin (KSPIN_DESCRIPTOR_EX structure). //pin (KSPIN_DESCRIPTOR_EX structure).
//Network provider and AVStream use this function //Network provider and AVStream use this function
//to connect the output pin with a downstream filter. //to connect the output pin with a downstream filter.
static NTSTATUS IntersectDataFormat( static NTSTATUS IntersectDataFormat(
IN PVOID pContext, IN PVOID pContext,
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSP_PIN Pin, IN PKSP_PIN Pin,
IN PKSDATARANGE DataRange, IN PKSDATARANGE DataRange,
IN PKSDATARANGE MatchingDataRange, IN PKSDATARANGE MatchingDataRange,
IN ULONG DataBufferSize, IN ULONG DataBufferSize,
OUT PVOID Data OPTIONAL, OUT PVOID Data OPTIONAL,
OUT PULONG DataSize OUT PULONG DataSize
); );
static NTSTATUS GetDigitalDemodProperty( static NTSTATUS GetDigitalDemodProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
); );
static NTSTATUS SetDigitalDemodProperty( static NTSTATUS SetDigitalDemodProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
); );
//Function to send the Extended BDA Commands to the Tuner //Function to send the Extended BDA Commands to the Tuner
static NTSTATUS SetExtendedProperty( static NTSTATUS SetExtendedProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
); );
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*__SKYWALKER1_TRANSPORT_PIN_H*/ #endif /*__SKYWALKER1_TRANSPORT_PIN_H*/

View File

@ -1,140 +1,140 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1TunerFilter.h File Name : SkyWalker1TunerFilter.h
Author : Author :
Date : Date :
Purpose : Tuner Filter Class Definition Purpose : Tuner Filter Class Definition
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef SKYWALKER1_TUNER_FILTER_H #ifndef SKYWALKER1_TUNER_FILTER_H
#define SKYWALKER1_TUNER_FILTER_H #define SKYWALKER1_TUNER_FILTER_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1CommonDef.h" #include "SkyWalker1CommonDef.h"
#include "SkyWalker1Device.h" #include "SkyWalker1Device.h"
#include "SkyWalker1Extended.h" #include "SkyWalker1Extended.h"
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
//The Tuner Filter class. //The Tuner Filter class.
class CTunerFilter class CTunerFilter
{ {
public: public:
//Functions to Create and Close Filter //Functions to Create and Close Filter
static NTSTATUS Create( IN OUT PKSFILTER pKSFilter, static NTSTATUS Create( IN OUT PKSFILTER pKSFilter,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
static NTSTATUS FilterClose( IN OUT PKSFILTER pKSFilter, static NTSTATUS FilterClose( IN OUT PKSFILTER pKSFilter,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
//KSMETHODSETID_BdaChangeSync pKSFilter change sync methods //KSMETHODSETID_BdaChangeSync pKSFilter change sync methods
static NTSTATUS StartChanges( IN PIRP pIoRequestPacket, static NTSTATUS StartChanges( IN PIRP pIoRequestPacket,
IN PKSMETHOD pKSMethod, IN PKSMETHOD pKSMethod,
OPTIONAL PVOID pvIgnored); OPTIONAL PVOID pvIgnored);
static NTSTATUS CheckChanges( IN PIRP pIoRequestPacket, static NTSTATUS CheckChanges( IN PIRP pIoRequestPacket,
IN PKSMETHOD pKSMethod, IN PKSMETHOD pKSMethod,
OPTIONAL PVOID pvIgnored); OPTIONAL PVOID pvIgnored);
static NTSTATUS CommitChanges( IN PIRP pIoRequestPacket, static NTSTATUS CommitChanges( IN PIRP pIoRequestPacket,
IN PKSMETHOD pKSMethod, IN PKSMETHOD pKSMethod,
OPTIONAL PVOID pvIgnored); OPTIONAL PVOID pvIgnored);
static NTSTATUS GetChangeState( IN PIRP pIoRequestPacket, static NTSTATUS GetChangeState( IN PIRP pIoRequestPacket,
IN PKSMETHOD pKSMethod, IN PKSMETHOD pKSMethod,
OUT PULONG pulChangeState); OUT PULONG pulChangeState);
//KSMETHODSETID_BdaDeviceConfiguration Method to modify filter topology. //KSMETHODSETID_BdaDeviceConfiguration Method to modify filter topology.
static NTSTATUS CreateTopology( IN PIRP pIoRequestPacket, static NTSTATUS CreateTopology( IN PIRP pIoRequestPacket,
IN PKSMETHOD pKSMethod, IN PKSMETHOD pKSMethod,
OPTIONAL PVOID pvIgnored); OPTIONAL PVOID pvIgnored);
//pKSFilter Implementation Methods //pKSFilter Implementation Methods
(class CSkyWalker1Device *) GetDevice() (class CSkyWalker1Device *) GetDevice()
{ {
return m_pDevice; return m_pDevice;
}; };
NTSTATUS SetDeviceState(KSSTATE NewKsState) NTSTATUS SetDeviceState(KSSTATE NewKsState)
{ {
m_KsState = NewKsState; m_KsState = NewKsState;
return STATUS_SUCCESS; return STATUS_SUCCESS;
}; };
//Tuner Node Properties //Tuner Node Properties
NTSTATUS GetTunerProperty(OUT PBDATUNER_DEVICE_PARAMETER pTunerParameter); NTSTATUS GetTunerProperty(OUT PBDATUNER_DEVICE_PARAMETER pTunerParameter);
NTSTATUS SetFrequency(IN ULONG ulBdaParameter); NTSTATUS SetFrequency(IN ULONG ulBdaParameter);
NTSTATUS SetMultiplier(IN ULONG ulBdaParameter); NTSTATUS SetMultiplier(IN ULONG ulBdaParameter);
NTSTATUS SetBandwidth(IN ULONG ulBdaParameter); NTSTATUS SetBandwidth(IN ULONG ulBdaParameter);
NTSTATUS SetPolarity(IN Polarisation NewPolarity); NTSTATUS SetPolarity(IN Polarisation NewPolarity);
NTSTATUS SetRange(IN ULONG ulBdaParameter); NTSTATUS SetRange(IN ULONG ulBdaParameter);
NTSTATUS SetTransponder(IN ULONG ulBdaParameter); NTSTATUS SetTransponder(IN ULONG ulBdaParameter);
NTSTATUS SetLowLOFrequency(IN ULONG ulBdaParameter); NTSTATUS SetLowLOFrequency(IN ULONG ulBdaParameter);
NTSTATUS SetHighLOFrequency(IN ULONG ulBdaParameter); NTSTATUS SetHighLOFrequency(IN ULONG ulBdaParameter);
NTSTATUS SetSwitchFrequency(IN ULONG ulBdaParameter); NTSTATUS SetSwitchFrequency(IN ULONG ulBdaParameter);
//Demodulator Node Properties //Demodulator Node Properties
NTSTATUS GetDemodProperty(OUT PBDATUNER_DEVICE_PARAMETER pDemodParameter); NTSTATUS GetDemodProperty(OUT PBDATUNER_DEVICE_PARAMETER pDemodParameter);
NTSTATUS SetModulatorType(IN ModulationType NewModulatorType); NTSTATUS SetModulatorType(IN ModulationType NewModulatorType);
NTSTATUS SetInnerFecType(IN ULONG ulNewInnerFecType); NTSTATUS SetInnerFecType(IN ULONG ulNewInnerFecType);
NTSTATUS SetInnerFecRate(IN BinaryConvolutionCodeRate NewFecRate); NTSTATUS SetInnerFecRate(IN BinaryConvolutionCodeRate NewFecRate);
NTSTATUS SetOuterFecType(IN ULONG ulNewOuterFecType); NTSTATUS SetOuterFecType(IN ULONG ulNewOuterFecType);
NTSTATUS SetOuterFecRate(IN BinaryConvolutionCodeRate NewFecRate); NTSTATUS SetOuterFecRate(IN BinaryConvolutionCodeRate NewFecRate);
NTSTATUS SetSymbolRate(IN ULONG ulNewSymbolRate); NTSTATUS SetSymbolRate(IN ULONG ulNewSymbolRate);
NTSTATUS SetSpectralInversion(IN SpectralInversion SpecInv); NTSTATUS SetSpectralInversion(IN SpectralInversion SpecInv);
NTSTATUS SetGuardInterval(IN GuardInterval GuardInt); NTSTATUS SetGuardInterval(IN GuardInterval GuardInt);
NTSTATUS SetTransmissionMode(IN TransmissionMode TransMode); NTSTATUS SetTransmissionMode(IN TransmissionMode TransMode);
//Extended Property //Extended Property
NTSTATUS SendDiseqcCommand(IN PDISEQC_COMMAND pDiseqcCommand); NTSTATUS SendDiseqcCommand(IN PDISEQC_COMMAND pDiseqcCommand);
//Function to retrive the Device Status. //Function to retrive the Device Status.
NTSTATUS GetStatus(PBDATUNER_DEVICE_STATUS pDeviceStatus); NTSTATUS GetStatus(PBDATUNER_DEVICE_STATUS pDeviceStatus);
//Functions to get and release device access //Functions to get and release device access
NTSTATUS AcquireResources(); NTSTATUS AcquireResources();
NTSTATUS ReleaseResources(); NTSTATUS ReleaseResources();
private: private:
class CSkyWalker1Device * m_pDevice; class CSkyWalker1Device * m_pDevice;
//Filter Resources //Filter Resources
KSSTATE m_KsState; KSSTATE m_KsState;
BDA_CHANGE_STATE m_BdaChangeState; BDA_CHANGE_STATE m_BdaChangeState;
BDATUNER_DEVICE_PARAMETER m_CurResource; BDATUNER_DEVICE_PARAMETER m_CurResource;
BDATUNER_DEVICE_PARAMETER m_NewResource; BDATUNER_DEVICE_PARAMETER m_NewResource;
ULONG m_ulResourceID; ULONG m_ulResourceID;
BOOLEAN m_fResourceAcquired; BOOLEAN m_fResourceAcquired;
CTunerFilter(); CTunerFilter();
~CTunerFilter(); ~CTunerFilter();
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*SKYWALKER1_TUNER_FILTER_H*/ #endif /*SKYWALKER1_TUNER_FILTER_H*/

View File

@ -1,82 +1,82 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1TunerPin.h File Name : SkyWalker1TunerPin.h
Author : Author :
Date : Date :
Purpose : This File Holds the Generic Tuner Pin related declarations Purpose : This File Holds the Generic Tuner Pin related declarations
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef __SKYWALKER1_TUNER_PIN_H #ifndef __SKYWALKER1_TUNER_PIN_H
#define __SKYWALKER1_TUNER_PIN_H #define __SKYWALKER1_TUNER_PIN_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1CommonDef.h" #include "SkyWalker1CommonDef.h"
#include "SkyWalker1TunerFilter.h" #include "SkyWalker1TunerFilter.h"
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
// The Tuner Pin class. // The Tuner Pin class.
class CTunerPin class CTunerPin
{ {
public: public:
//Creates the Pin //Creates the Pin
static NTSTATUS PinCreate( IN OUT PKSPIN pKSPin, static NTSTATUS PinCreate( IN OUT PKSPIN pKSPin,
IN PIRP pIoRequestPacket IN PIRP pIoRequestPacket
); );
//Closes the Opened Pin //Closes the Opened Pin
static NTSTATUS PinClose( IN OUT PKSPIN pKSPin, static NTSTATUS PinClose( IN OUT PKSPIN pKSPin,
IN PIRP pIoRequestPacket IN PIRP pIoRequestPacket
); );
//Member Function to get the Various Signal attributes //Member Function to get the Various Signal attributes
static NTSTATUS GetSignalStatus( static NTSTATUS GetSignalStatus(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
); );
(class CTunerFilter *) GetFilter(void) (class CTunerFilter *) GetFilter(void)
{ {
return m_pFilter; return m_pFilter;
}; };
void SetFilter(class CTunerFilter * pFilter) void SetFilter(class CTunerFilter * pFilter)
{ {
m_pFilter = pFilter; m_pFilter = pFilter;
}; };
protected: protected:
class CTunerFilter* m_pFilter; class CTunerFilter* m_pFilter;
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*__SKYWALKER1_TUNER_PIN_H*/ #endif /*__SKYWALKER1_TUNER_PIN_H*/

View File

@ -1,126 +1,126 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1Usb.h File Name : SkyWalker1Usb.h
Author : Author :
Date : Date :
Purpose : This File Holds all the USB Device access related declarations Purpose : This File Holds all the USB Device access related declarations
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef __SKYWALKER1_USB_H #ifndef __SKYWALKER1_USB_H
#define __SKYWALKER1_USB_H #define __SKYWALKER1_USB_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
extern "C" extern "C"
{ {
//USB Related Headers //USB Related Headers
#include <initguid.h> #include <initguid.h>
#pragma warning(disable:4200) #pragma warning(disable:4200)
#include <usbdi.h> #include <usbdi.h>
#include <usbdlib.h> #include <usbdlib.h>
#include <stdio.h> #include <stdio.h>
#include <usb100.h> #include <usb100.h>
#include "SkyWalker1Device.h" #include "SkyWalker1Device.h"
} }
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
#define MAX_BULK_PACKET_SIZE 8 * 512 #define MAX_BULK_PACKET_SIZE 8 * 512
#define MAX_BULK_TRANSFER_SIZE (TRANSPORT_PACKET_COUNT * TRANSPORT_PACKET_SIZE) //Suppoting max Frame Size #define MAX_BULK_TRANSFER_SIZE (TRANSPORT_PACKET_COUNT * TRANSPORT_PACKET_SIZE) //Suppoting max Frame Size
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Declare Enumerations here */ /* Declare Enumerations here */
typedef enum __USBSTATE { typedef enum __USBSTATE {
NotStarted, // not started NotStarted, // not started
Stopped, // device stopped Stopped, // device stopped
Working, // started and working Working, // started and working
PendingStop, // stop pending PendingStop, // stop pending
PendingRemove, // remove pending PendingRemove, // remove pending
SurpriseRemoved, // removed by surprise SurpriseRemoved, // removed by surprise
Removed // removed Removed // removed
}USBSTATE; }USBSTATE;
typedef enum _QUEUE_STATE { typedef enum _QUEUE_STATE {
HoldRequests, // device is not started yet HoldRequests, // device is not started yet
AllowRequests, // device is ready to process AllowRequests, // device is ready to process
FailRequests // fail both existing and queued up requests FailRequests // fail both existing and queued up requests
} QUEUE_STATE; } QUEUE_STATE;
#define INITIALIZE_PNP_STATE(_Data_) \ #define INITIALIZE_PNP_STATE(_Data_) \
(_Data_)->UsbDeviceState = NotStarted;\ (_Data_)->UsbDeviceState = NotStarted;\
(_Data_)->PreviousUsbDeviceState = NotStarted; (_Data_)->PreviousUsbDeviceState = NotStarted;
#define SET_NEW_PNP_STATE(_Data_, _state_) \ #define SET_NEW_PNP_STATE(_Data_, _state_) \
(_Data_)->PreviousUsbDeviceState = (_Data_)->UsbDeviceState;\ (_Data_)->PreviousUsbDeviceState = (_Data_)->UsbDeviceState;\
(_Data_)->UsbDeviceState = (_state_); (_Data_)->UsbDeviceState = (_state_);
#define RESTORE_PREVIOUS_PNP_STATE(_Data_) \ #define RESTORE_PREVIOUS_PNP_STATE(_Data_) \
(_Data_)->UsbDeviceState = (_Data_)->PreviousUsbDeviceState; (_Data_)->UsbDeviceState = (_Data_)->PreviousUsbDeviceState;
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
//BulkUsb Read Write Context //BulkUsb Read Write Context
typedef struct _BULKUSB_RW_CONTEXT { typedef struct _BULKUSB_RW_CONTEXT {
PURB pUSBRequestBlock; PURB pUSBRequestBlock;
PUCHAR pTransferBuffer; PUCHAR pTransferBuffer;
ULONG ulRemainingByteTransfer; // remaining to xfer ULONG ulRemainingByteTransfer; // remaining to xfer
ULONG ulCompletedByteTransfer; // cumulate xfer ULONG ulCompletedByteTransfer; // cumulate xfer
ULONG ulStreamIndex; ULONG ulStreamIndex;
class CSkyWalker1Device * pDevice; class CSkyWalker1Device * pDevice;
} BULKUSB_RW_CONTEXT, * PBULKUSB_RW_CONTEXT; } BULKUSB_RW_CONTEXT, * PBULKUSB_RW_CONTEXT;
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Function Prototypes */ /* Function Prototypes */
//Usb Access functions //Usb Access functions
NTSTATUS InitializeUsbDevice(IN PKSDEVICE pKSDeviceObject, NTSTATUS InitializeUsbDevice(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoReqestPacket); IN PIRP pIoReqestPacket);
NTSTATUS DeconfigureUsbDevice(IN PKSDEVICE pKSDeviceObject); NTSTATUS DeconfigureUsbDevice(IN PKSDEVICE pKSDeviceObject);
NTSTATUS StopUsbDevice(IN PKSDEVICE pKSDeviceObject, NTSTATUS StopUsbDevice(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS ReadWriteUsbDevice(IN PKSDEVICE pKSDeviceObject, NTSTATUS ReadWriteUsbDevice(IN PKSDEVICE pKSDeviceObject,
IN ULONG ulStreamIndex, IN ULONG ulStreamIndex,
IN ULONG ulPacketIndex, IN ULONG ulPacketIndex,
IN PUCHAR pucTransferBuffer, IN PUCHAR pucTransferBuffer,
IN ULONG ulTransferLength, IN ULONG ulTransferLength,
IN BOOLEAN bRead); IN BOOLEAN bRead);
NTSTATUS ControlUsbDevice( IN PKSDEVICE pKSDeviceObject, NTSTATUS ControlUsbDevice( IN PKSDEVICE pKSDeviceObject,
IN UCHAR ucRequest, IN UCHAR ucRequest,
IN USHORT usValue, IN USHORT usValue,
IN USHORT usIndex, IN USHORT usIndex,
IN PUCHAR pucTransferBuffer, IN PUCHAR pucTransferBuffer,
IN ULONG ulTransferLength, IN ULONG ulTransferLength,
IN BOOLEAN bRead); IN BOOLEAN bRead);
NTSTATUS RemoveUsbDevice( IN PKSDEVICE pKSDeviceObject, NTSTATUS RemoveUsbDevice( IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS SurpriseUsbDeviceRemoval(IN PKSDEVICE pKSDeviceObject, NTSTATUS SurpriseUsbDeviceRemoval(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS CancelRemoveUsbDevice(IN PKSDEVICE pKSDeviceObject, NTSTATUS CancelRemoveUsbDevice(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS QueryRemoveUsbDevice( IN PKSDEVICE pKSDeviceObject, NTSTATUS QueryRemoveUsbDevice( IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS QueryStopUsbDevice(IN PKSDEVICE pKSDeviceObject, NTSTATUS QueryStopUsbDevice(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
NTSTATUS CancelStopUsbDevice(IN PKSDEVICE pKSDeviceObject, NTSTATUS CancelStopUsbDevice(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*__SKYWALKER1_USB_H*/ #endif /*__SKYWALKER1_USB_H*/

View File

@ -1,91 +1,91 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1Utility.h File Name : SkyWalker1Utility.h
Author : Author :
Date : Date :
Purpose : This file basically holds the Utility related Common Declarations Purpose : This file basically holds the Utility related Common Declarations
used in the SkyWalker Driver Module used in the SkyWalker Driver Module
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
#ifndef SKYWALKER1_UTILITY_H #ifndef SKYWALKER1_UTILITY_H
#define SKYWALKER1_UTILITY_H #define SKYWALKER1_UTILITY_H
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include <wdm.h> #include <wdm.h>
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
#define SKYWALKER1_DRIVER_NAME "SkyWalker1TVTuner" #define SKYWALKER1_DRIVER_NAME "SkyWalker1TVTuner"
extern int nCurrentDebugLevel; extern int nCurrentDebugLevel;
#define DEBUG_ON #define DEBUG_ON
#ifdef DEBUG_ON #ifdef DEBUG_ON
#define SkyWalkerDebugPrint(DebugLevel,_ARGUMENTS_) \ #define SkyWalkerDebugPrint(DebugLevel,_ARGUMENTS_) \
if((DebugLevel) <= nCurrentDebugLevel) \ if((DebugLevel) <= nCurrentDebugLevel) \
{ \ { \
DbgPrint _ARGUMENTS_; \ DbgPrint _ARGUMENTS_; \
} }
#else #else
#define SkyWalkerDebugPrint(DebugLevel,__ARGUMENTS__) #define SkyWalkerDebugPrint(DebugLevel,__ARGUMENTS__)
#endif #endif
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* ENUM : enDebugLevels */ /* ENUM : enDebugLevels */
/* PURPOSE : To Define Different Debug Levels */ /* PURPOSE : To Define Different Debug Levels */
enum enDebugLevels enum enDebugLevels
{ {
DISABLE_DEBUG = 0, DISABLE_DEBUG = 0,
ENTRY_LEVEL, ENTRY_LEVEL,
INTERMEDIATE_LEVEL, INTERMEDIATE_LEVEL,
EXTREME_LEVEL, EXTREME_LEVEL,
}; };
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
void PrintFunctionEntry(IN char * pcFunctionName); void PrintFunctionEntry(IN char * pcFunctionName);
void PrintFunctionExit(IN char * pcFunctionName, IN NTSTATUS ntReturnCode); void PrintFunctionExit(IN char * pcFunctionName, IN NTSTATUS ntReturnCode);
char * GetCurrentIrqlString(void); char * GetCurrentIrqlString(void);
VOID Delay(IN ULONG ulDelayInMicroSeconds); //To Delay the Execution Thread VOID Delay(IN ULONG ulDelayInMicroSeconds); //To Delay the Execution Thread
NTSTATUS LowerDeviceCompletedIrp(IN PDEVICE_OBJECT pDeviceObject, NTSTATUS LowerDeviceCompletedIrp(IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PVOID pContext); IN PVOID pContext);
NTSTATUS PassDownIRPAndWaitForCompletion(IN PDEVICE_OBJECT pLowerDeviceObject, NTSTATUS PassDownIRPAndWaitForCompletion(IN PDEVICE_OBJECT pLowerDeviceObject,
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN BOOLEAN bCopyStackLocation); IN BOOLEAN bCopyStackLocation);
NTSTATUS PassDownIRPAndForget(IN PDEVICE_OBJECT pLowerDeviceObject, NTSTATUS PassDownIRPAndForget(IN PDEVICE_OBJECT pLowerDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
VOID CompleteIrpInDispatch(IN PDEVICE_OBJECT pDeviceObject, VOID CompleteIrpInDispatch(IN PDEVICE_OBJECT pDeviceObject,
IN PIRP pIoRequestPacket); IN PIRP pIoRequestPacket);
PUCHAR NTStatusToString(NTSTATUS Status) ; PUCHAR NTStatusToString(NTSTATUS Status) ;
VOID PrintDeviceChangeState(IN KSSTATE ToState,IN KSSTATE FromState); VOID PrintDeviceChangeState(IN KSSTATE ToState,IN KSSTATE FromState);
/* End of Function prototype definitions */ /* End of Function prototype definitions */
#endif /*SKYWALKER1_UTILITY_H*/ #endif /*SKYWALKER1_UTILITY_H*/

View File

@ -1,165 +1,165 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1CaptureFilter.cpp File Name : SkyWalker1CaptureFilter.cpp
Author : Author :
Date : Date :
Purpose : This file contains the filter level header for the Purpose : This file contains the filter level header for the
capture filter. capture filter.
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1Main.h" //Main Header file #include "SkyWalker1Main.h" //Main Header file
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
/***************************************************************************** /*****************************************************************************
Function : CCaptureFilter Function : CCaptureFilter
Description : Constructor of the CCaptureFilter Class Description : Constructor of the CCaptureFilter Class
The capture filter object constructor. Since the new operator will The capture filter object constructor. Since the new operator will
have zeroed the memory, do not bother initializing any NULL or 0 have zeroed the memory, do not bother initializing any NULL or 0
fields.Only initialize non-NULL, non-0 fields. fields.Only initialize non-NULL, non-0 fields.
IN PARAM : <PKSFILTER> Filter IN PARAM : <PKSFILTER> Filter
OUT PARAM : NONE OUT PARAM : NONE
PreCondition : Filter Object is not created PreCondition : Filter Object is not created
PostCondtion : Filter Object is created and Initialzed on successful execution PostCondtion : Filter Object is created and Initialzed on successful execution
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
CCaptureFilter::CCaptureFilter(IN PKSFILTER pKSFilter) : CCaptureFilter::CCaptureFilter(IN PKSFILTER pKSFilter) :
m_Filter (pKSFilter) m_Filter (pKSFilter)
{ {
} }
/***************************************************************************** /*****************************************************************************
Function : CCaptureFilter Function : CCaptureFilter
Description : Destructor of the CCaptureFilter Class Description : Destructor of the CCaptureFilter Class
Destroys the filter object Destroys the filter object
IN PARAM : NONE IN PARAM : NONE
OUT PARAM : NONE OUT PARAM : NONE
PreCondition : Filter Object is created PreCondition : Filter Object is created
PostCondtion : Filter Object is Removed and Memory freed PostCondtion : Filter Object is Removed and Memory freed
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
CCaptureFilter::~CCaptureFilter() CCaptureFilter::~CCaptureFilter()
{ {
} }
/***************************************************************************** /*****************************************************************************
Function : CCaptureFilter::Cleanup() Function : CCaptureFilter::Cleanup()
Description : This is the bag cleanup callback for the CCaptureFilter. Description : This is the bag cleanup callback for the CCaptureFilter.
Destroys the filter object Destroys the filter object
IN PARAM : <CCaptureFilter> Reference to the current Object IN PARAM : <CCaptureFilter> Reference to the current Object
OUT PARAM : NONE OUT PARAM : NONE
PreCondition : Filter Object is created PreCondition : Filter Object is created
PostCondtion : Filter Object is Removed and Memory freed PostCondtion : Filter Object is Removed and Memory freed
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
void CCaptureFilter::Cleanup (IN CCaptureFilter *pFilter) void CCaptureFilter::Cleanup (IN CCaptureFilter *pFilter)
{ {
delete pFilter; delete pFilter;
} }
/***************************************************************************** /*****************************************************************************
Function : CCaptureFilter::Create() Function : CCaptureFilter::Create()
Description : It creates the CCaptureFilter object, associates it with Description : It creates the CCaptureFilter object, associates it with
the AVStream filter object, and bag the CCaptureFilter the AVStream filter object, and bag the CCaptureFilter
for later cleanup. for later cleanup.
IN PARAM : <PKSFILTER > Pointer to KSFILTER that just created IN PARAM : <PKSFILTER > Pointer to KSFILTER that just created
<PIRP> Pointer to IRP_MJ_CREATE for Filter <PIRP> Pointer to IRP_MJ_CREATE for Filter
OUT PARAM : <NTSTATUS> Status of the Filter Create routine OUT PARAM : <NTSTATUS> Status of the Filter Create routine
STATUS_SUCCESS on Routine success STATUS_SUCCESS on Routine success
Else Error code from the attempt to create the Filter Else Error code from the attempt to create the Filter
PreCondition : Filter is not created PreCondition : Filter is not created
PostCondtion : Filter is created and Initialzed on successful execution PostCondtion : Filter is created and Initialzed on successful execution
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
STDMETHODIMP_(NTSTATUS) CCaptureFilter::Create( IN OUT PKSFILTER pKSFilter, STDMETHODIMP_(NTSTATUS) CCaptureFilter::Create( IN OUT PKSFILTER pKSFilter,
IN PIRP pIoRequestPacket) IN PIRP pIoRequestPacket)
{ {
NTSTATUS ntFilterCreationStatus = STATUS_SUCCESS; NTSTATUS ntFilterCreationStatus = STATUS_SUCCESS;
ULONG ulPinId; // just useful when no network provider is present ULONG ulPinId; // just useful when no network provider is present
PKSDEVICE pKSDeviceObject = NULL; PKSDEVICE pKSDeviceObject = NULL;
CSkyWalker1Device * pDevice = NULL; CSkyWalker1Device * pDevice = NULL;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
//Create a filter object for the filter instance. //Create a filter object for the filter instance.
CCaptureFilter* pFilter = new(NonPagedPool,CAPTURE_MEM_TAG) CCaptureFilter(pKSFilter); // Tags the allocated memory CCaptureFilter* pFilter = new(NonPagedPool,CAPTURE_MEM_TAG) CCaptureFilter(pKSFilter); // Tags the allocated memory
if (!IS_VALID(pFilter)) if (!IS_VALID(pFilter))
{ {
//Exit if the Filter Memory could not be allocated //Exit if the Filter Memory could not be allocated
ntFilterCreationStatus = STATUS_INSUFFICIENT_RESOURCES; ntFilterCreationStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ErrorFilterCreate; goto ErrorFilterCreate;
} }
else else
{ {
// Add the item to the object bag if we we were successful. // Add the item to the object bag if we we were successful.
// Whenever the filter closes, the bag is cleaned up and we will be // Whenever the filter closes, the bag is cleaned up and we will be
// freed. // freed.
// //
ntFilterCreationStatus = KsAddItemToObjectBag ( ntFilterCreationStatus = KsAddItemToObjectBag (
pKSFilter -> Bag, pKSFilter -> Bag,
reinterpret_cast <PVOID> (pFilter), reinterpret_cast <PVOID> (pFilter),
reinterpret_cast <PFNKSFREE> (CCaptureFilter::Cleanup) reinterpret_cast <PFNKSFREE> (CCaptureFilter::Cleanup)
); );
if (!NT_SUCCESS (ntFilterCreationStatus)) if (!NT_SUCCESS (ntFilterCreationStatus))
{ {
goto ErrorFilterCreate; goto ErrorFilterCreate;
} }
else else
{ {
pKSFilter->Context = reinterpret_cast <PVOID> (pFilter); pKSFilter->Context = reinterpret_cast <PVOID> (pFilter);
} }
} }
CompleteFilterCreate : CompleteFilterCreate :
PrintFunctionExit(__FUNCTION__,ntFilterCreationStatus); PrintFunctionExit(__FUNCTION__,ntFilterCreationStatus);
return ntFilterCreationStatus; return ntFilterCreationStatus;
ErrorFilterCreate: ErrorFilterCreate:
if (IS_VALID(pFilter)) if (IS_VALID(pFilter))
{ {
delete pFilter; delete pFilter;
} }
goto CompleteFilterCreate; goto CompleteFilterCreate;
} }

View File

@ -1,336 +1,336 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1CaptureFilterDefinitions.cpp File Name : SkyWalker1CaptureFilterDefinitions.cpp
Author : Author :
Date : Date :
Purpose : Capture Filter Definition Purpose : Capture Filter Definition
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1Main.h" //Main Header file #include "SkyWalker1Main.h" //Main Header file
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
const KSPIN_DISPATCH CaptureInputPinDispatch={ const KSPIN_DISPATCH CaptureInputPinDispatch={
/* Create */ CCapturePin::PinCreate, /* Create */ CCapturePin::PinCreate,
/* Close */ NULL, /* Close */ NULL,
/* Process */ NULL, /* Process */ NULL,
/* Reset */ NULL, /* Reset */ NULL,
/* SetDataFormat */ NULL, /* SetDataFormat */ NULL,
/* SetDeviceState */ NULL, /* SetDeviceState */ NULL,
/* Connect */ NULL, /* Connect */ NULL,
/* Disconnect */ NULL, /* Disconnect */ NULL,
/* Allocator */ NULL /* Allocator */ NULL
}; };
DEFINE_KSAUTOMATION_TABLE(NullAutomation) { DEFINE_KSAUTOMATION_TABLE(NullAutomation) {
DEFINE_KSAUTOMATION_PROPERTIES_NULL, DEFINE_KSAUTOMATION_PROPERTIES_NULL,
DEFINE_KSAUTOMATION_METHODS_NULL, DEFINE_KSAUTOMATION_METHODS_NULL,
DEFINE_KSAUTOMATION_EVENTS_NULL DEFINE_KSAUTOMATION_EVENTS_NULL
}; };
//The list of category GUIDs for the capture filter. //The list of category GUIDs for the capture filter.
const GUID SkyWalker1CaptureCatagories [] = { const GUID SkyWalker1CaptureCatagories [] = {
STATICGUIDOF (KSCATEGORY_BDA_RECEIVER_COMPONENT) STATICGUIDOF (KSCATEGORY_BDA_RECEIVER_COMPONENT)
}; };
//Medium GUIDs for the Transport Output Pin. //Medium GUIDs for the Transport Output Pin.
// //
//Pin Medium descriptor containing all medium accepted to be connected to //Pin Medium descriptor containing all medium accepted to be connected to
//the tuner output pin.This insures contection to the correct Capture Filter pin. //the tuner output pin.This insures contection to the correct Capture Filter pin.
// //
//{2AEB4A94-FBB7-4FB1-8D74-243B91886EAB} //{2AEB4A94-FBB7-4FB1-8D74-243B91886EAB}
const KSPIN_MEDIUM TransportPinMediums[] = const KSPIN_MEDIUM TransportPinMediums[] =
{ {
{ {
GUID_SKYWALKER_TUNER_OUT_MEDIUM, GUID_SKYWALKER_TUNER_OUT_MEDIUM,
0, 0,
0 0
} }
}; };
// //
//This is the data range description of the capture input pin. //This is the data range description of the capture input pin.
//This is same as the Outpin of the Tuner i.e. The Transport Pin //This is same as the Outpin of the Tuner i.e. The Transport Pin
//The Output of the Tuner is given to the Capture thus it has to //The Output of the Tuner is given to the Capture thus it has to
//be same //be same
// //
const KS_DATARANGE_BDA_TRANSPORT FormatCaptureIn = const KS_DATARANGE_BDA_TRANSPORT FormatCaptureIn =
{ {
//insert the KSDATARANGE and KSDATAFORMAT here //insert the KSDATARANGE and KSDATAFORMAT here
{ {
sizeof( KS_DATARANGE_BDA_TRANSPORT), //FormatSize sizeof( KS_DATARANGE_BDA_TRANSPORT), //FormatSize
0, //Flags - (N/A) 0, //Flags - (N/A)
0, //SampleSize - (N/A) 0, //SampleSize - (N/A)
0, //Reserved 0, //Reserved
{ STATIC_KSDATAFORMAT_TYPE_STREAM }, //MajorFormat { STATIC_KSDATAFORMAT_TYPE_STREAM }, //MajorFormat
{ STATIC_KSDATAFORMAT_TYPE_MPEG2_TRANSPORT }, //SubFormat { STATIC_KSDATAFORMAT_TYPE_MPEG2_TRANSPORT }, //SubFormat
{ STATIC_KSDATAFORMAT_SPECIFIER_BDA_TRANSPORT } //Specifier { STATIC_KSDATAFORMAT_SPECIFIER_BDA_TRANSPORT } //Specifier
}, },
//insert the BDA_TRANSPORT_INFO here //insert the BDA_TRANSPORT_INFO here
{ {
TRANSPORT_PACKET_SIZE, //ulcbPhyiscalPacket TRANSPORT_PACKET_SIZE, //ulcbPhyiscalPacket
TRANSPORT_PACKET_COUNT*TRANSPORT_PACKET_SIZE, //ulcbPhyiscalFrame TRANSPORT_PACKET_COUNT*TRANSPORT_PACKET_SIZE, //ulcbPhyiscalFrame
0, //ulcbPhyiscalFrameAlignment (no requirement) 0, //ulcbPhyiscalFrameAlignment (no requirement)
0 //AvgTimePerFrame (not known) 0 //AvgTimePerFrame (not known)
} }
}; };
const PKSDATARANGE CaptureInPinDataRanges[]={ const PKSDATARANGE CaptureInPinDataRanges[]={
(PKSDATARANGE)&FormatCaptureIn, (PKSDATARANGE)&FormatCaptureIn,
}; };
//Capture Outout Pin Definitions //Capture Outout Pin Definitions
const KSPIN_DISPATCH CaptureOutputPinDispatch={ const KSPIN_DISPATCH CaptureOutputPinDispatch={
/* Create */ CCapturePin::PinCreate, /* Create */ CCapturePin::PinCreate,
/* Close */ NULL, /* Close */ NULL,
/* Process */ CCapturePin::DispatchProcess, /* Process */ CCapturePin::DispatchProcess,
/* Reset */ NULL, /* Reset */ NULL,
/* SetDataFormat */ NULL, /* SetDataFormat */ NULL,
/* SetDeviceState */ CCapturePin::DispatchSetState, /* SetDeviceState */ CCapturePin::DispatchSetState,
/* Connect */ NULL, /* Connect */ NULL,
/* Disconnect */ NULL, /* Disconnect */ NULL,
/* Allocator */ NULL /* Allocator */ NULL
}; };
// //
//This is the data range description of the capture output pin. //This is the data range description of the capture output pin.
// //
const KSDATARANGE FormatCaptureOut = const KSDATARANGE FormatCaptureOut =
{ {
//insert the KSDATARANGE and KSDATAFORMAT here //insert the KSDATARANGE and KSDATAFORMAT here
{ {
sizeof( KSDATARANGE), //FormatSize sizeof( KSDATARANGE), //FormatSize
0, //Flags - (N/A) 0, //Flags - (N/A)
TRANSPORT_PACKET_COUNT*TRANSPORT_PACKET_SIZE, //SampleSize TRANSPORT_PACKET_COUNT*TRANSPORT_PACKET_SIZE, //SampleSize
0, //Reserved 0, //Reserved
{ STATIC_KSDATAFORMAT_TYPE_STREAM }, //MajorFormat { STATIC_KSDATAFORMAT_TYPE_STREAM }, //MajorFormat
{ STATIC_KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT },//SubFormat { STATIC_KSDATAFORMAT_SUBTYPE_BDA_MPEG2_TRANSPORT },//SubFormat
{ STATIC_KSDATAFORMAT_SPECIFIER_NONE } //Specifier { STATIC_KSDATAFORMAT_SPECIFIER_NONE } //Specifier
} }
}; };
const PKSDATARANGE CaptureOutPinDataRanges[]={ const PKSDATARANGE CaptureOutPinDataRanges[]={
(PKSDATARANGE)&FormatCaptureOut, (PKSDATARANGE)&FormatCaptureOut,
}; };
// //
//CapturePinAllocatorFraming: //CapturePinAllocatorFraming:
// //
//This is the simple framing structure for the capture pin. Note that this //This is the simple framing structure for the capture pin. Note that this
//will be modified via KsEdit when the actual capture format is determined. //will be modified via KsEdit when the actual capture format is determined.
// //
DECLARE_SIMPLE_FRAMING_EX ( DECLARE_SIMPLE_FRAMING_EX (
CapturePinAllocatorFraming, //FramingExName CapturePinAllocatorFraming, //FramingExName
STATICGUIDOF (KSMEMORY_TYPE_KERNEL_NONPAGED), //MemoryType STATICGUIDOF (KSMEMORY_TYPE_KERNEL_NONPAGED), //MemoryType
KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY | KSALLOCATOR_REQUIREMENTF_SYSTEM_MEMORY |
KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY, //Flags KSALLOCATOR_REQUIREMENTF_PREFERENCES_ONLY, //Flags
NUMBER_OF_FRAMES, //Frames NUMBER_OF_FRAMES, //Frames
0, //Alignment 0, //Alignment
TRANSPORT_PACKET_COUNT*TRANSPORT_PACKET_SIZE, //MinFrameSize TRANSPORT_PACKET_COUNT*TRANSPORT_PACKET_SIZE, //MinFrameSize
TRANSPORT_PACKET_COUNT*TRANSPORT_PACKET_SIZE //MaxFrameSize TRANSPORT_PACKET_COUNT*TRANSPORT_PACKET_SIZE //MaxFrameSize
); );
/**********************************************************************************/ /**********************************************************************************/
//Not Supporting Filter Methods,Properties and Events //Not Supporting Filter Methods,Properties and Events
DEFINE_KSAUTOMATION_TABLE(SkyWalker1CaptureAutomationTable) DEFINE_KSAUTOMATION_TABLE(SkyWalker1CaptureAutomationTable)
{ {
DEFINE_KSAUTOMATION_PROPERTIES_NULL, DEFINE_KSAUTOMATION_PROPERTIES_NULL,
DEFINE_KSAUTOMATION_METHODS_NULL, DEFINE_KSAUTOMATION_METHODS_NULL,
DEFINE_KSAUTOMATION_EVENTS_NULL DEFINE_KSAUTOMATION_EVENTS_NULL
}; };
/**********************************************************************************/ /**********************************************************************************/
// //
//CaptureFilterDispatch: //CaptureFilterDispatch:
// //
//This is the dispatch table for the capture filter. It provides notification //This is the dispatch table for the capture filter. It provides notification
//of creation, closure, processing (for filter-centrics, not for the capture //of creation, closure, processing (for filter-centrics, not for the capture
//filter), and resets (for filter-centrics, not for the capture filter). //filter), and resets (for filter-centrics, not for the capture filter).
// //
const KSFILTER_DISPATCH SkyWalker1CaptureDispatchTable = const KSFILTER_DISPATCH SkyWalker1CaptureDispatchTable =
{ {
/* Create */ CCaptureFilter::Create, //Routine called when the Filter is created /* Create */ CCaptureFilter::Create, //Routine called when the Filter is created
/* Close */ NULL, //Routine called when the Filter is closed /* Close */ NULL, //Routine called when the Filter is closed
/* Process */ NULL, /* Process */ NULL,
/* Reset */ NULL /* Reset */ NULL
}; };
// //
//Capture Pin Descriptors //Capture Pin Descriptors
// //
//This data structure defines the pin types available in the filters //This data structure defines the pin types available in the filters
//template topology. These structures will be used to create a //template topology. These structures will be used to create a
//KDPinFactory for a pin type when BdaCreatePin or BdaMethodCreatePin //KDPinFactory for a pin type when BdaCreatePin or BdaMethodCreatePin
//are called. //are called.
// //
//This structure defines ALL pins the filter is capable of supporting, //This structure defines ALL pins the filter is capable of supporting,
//including those pins which may only be created dynamically by a ring //including those pins which may only be created dynamically by a ring
//3 component such as a Network Provider. //3 component such as a Network Provider.
//The list of pin descriptors on the capture filter. //The list of pin descriptors on the capture filter.
const KSPIN_DESCRIPTOR_EX SkyWalker1CapturePinDescriptors[]={ const KSPIN_DESCRIPTOR_EX SkyWalker1CapturePinDescriptors[]={
{ //Capture Filter input pin { //Capture Filter input pin
&CaptureInputPinDispatch, //Dispatch Table &CaptureInputPinDispatch, //Dispatch Table
&NullAutomation, //Automation Table &NullAutomation, //Automation Table
{ {
0, //Interfaces 0, //Interfaces
NULL, NULL,
SIZEOF_ARRAY(TransportPinMediums), //Medium Count SIZEOF_ARRAY(TransportPinMediums), //Medium Count
TransportPinMediums, //Medium TransportPinMediums, //Medium
SIZEOF_ARRAY(CaptureInPinDataRanges), //Range Count SIZEOF_ARRAY(CaptureInPinDataRanges), //Range Count
CaptureInPinDataRanges, //Ranges CaptureInPinDataRanges, //Ranges
KSPIN_DATAFLOW_IN, //Specifies that data flow is into the pin KSPIN_DATAFLOW_IN, //Specifies that data flow is into the pin
KSPIN_COMMUNICATION_BOTH, //Specifies that the pin factory instantiates pins KSPIN_COMMUNICATION_BOTH, //Specifies that the pin factory instantiates pins
//that are both IRP sinks and IRP sources //that are both IRP sinks and IRP sources
(GUID *) &PINNAME_BDA_TRANSPORT, //Category GUID (GUID *) &PINNAME_BDA_TRANSPORT, //Category GUID
(GUID *) &PINNAME_BDA_TRANSPORT, //GUID of the localized Unicode string (GUID *) &PINNAME_BDA_TRANSPORT, //GUID of the localized Unicode string
0 0
}, },
KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT| KSPIN_FLAG_DO_NOT_USE_STANDARD_TRANSPORT|
KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING| KSPIN_FLAG_FRAMES_NOT_REQUIRED_FOR_PROCESSING|
KSPIN_FLAG_FIXED_FORMAT, KSPIN_FLAG_FIXED_FORMAT,
1, //Maximum Possible Instances of the Pin 1, //Maximum Possible Instances of the Pin
1, //Mandatory Instances of this for the Filter function 1, //Mandatory Instances of this for the Filter function
NULL,//Allocator Framing NULL,//Allocator Framing
NULL //Data Interaction Handler NULL //Data Interaction Handler
}, },
{ //Capture Filter output pin { //Capture Filter output pin
&CaptureOutputPinDispatch, //Dispatch Table &CaptureOutputPinDispatch, //Dispatch Table
&NullAutomation, //Automation Table &NullAutomation, //Automation Table
{ {
NULL, NULL,
0, 0,
NULL, NULL,
0, 0,
SIZEOF_ARRAY(CaptureOutPinDataRanges), //Range Count SIZEOF_ARRAY(CaptureOutPinDataRanges), //Range Count
CaptureOutPinDataRanges, CaptureOutPinDataRanges,
KSPIN_DATAFLOW_OUT, //Specifies that data flow is out of the pin KSPIN_DATAFLOW_OUT, //Specifies that data flow is out of the pin
KSPIN_COMMUNICATION_BOTH,//Specifies that the pin factory instantiates pins KSPIN_COMMUNICATION_BOTH,//Specifies that the pin factory instantiates pins
//that are both IRP sinks and IRP sources //that are both IRP sinks and IRP sources
(GUID *) &PINNAME_BDA_TRANSPORT, //Category GUID (GUID *) &PINNAME_BDA_TRANSPORT, //Category GUID
(GUID *) &PINNAME_BDA_TRANSPORT, //GUID of the localized Unicode string (GUID *) &PINNAME_BDA_TRANSPORT, //GUID of the localized Unicode string
0 0
}, },
#if !defined(_BUILD_SW_TUNER_ON_X64) #if !defined(_BUILD_SW_TUNER_ON_X64)
KSPIN_FLAG_GENERATE_MAPPINGS | //Pin Flags KSPIN_FLAG_GENERATE_MAPPINGS | //Pin Flags
#endif #endif
KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY, KSPIN_FLAG_PROCESS_IN_RUN_STATE_ONLY,
1,//Maximum Possible Instances of the Pin 1,//Maximum Possible Instances of the Pin
1,//Mandatory Instances of this for the Filter function 1,//Mandatory Instances of this for the Filter function
&CapturePinAllocatorFraming, &CapturePinAllocatorFraming,
NULL NULL
}, },
}; };
/*****************************************************************************************/ /*****************************************************************************************/
//Define BDA Template Topology Connections //Define BDA Template Topology Connections
// //
//Lists the Connections that are possible between pin types and //Lists the Connections that are possible between pin types and
//node types. This, together with the Template Filter Descriptor, and //node types. This, together with the Template Filter Descriptor, and
//the Pin Pairings, describe how topologies can be created in the filter. //the Pin Pairings, describe how topologies can be created in the filter.
// //
// ================= // =================
//TransportPin ----| Capture Filter | //TransportPin ----| Capture Filter |
// ================= // =================
// //
//The Capture Filter is controlled by the Transport input pin. //The Capture Filter is controlled by the Transport input pin.
//Capture Filter properties will be set as NODE properties (with NodeType == 0) //Capture Filter properties will be set as NODE properties (with NodeType == 0)
//on the filter's Tranport Pin //on the filter's Tranport Pin
// //
const KSTOPOLOGY_CONNECTION SkyWalker1CaptureConnections[]={ const KSTOPOLOGY_CONNECTION SkyWalker1CaptureConnections[]={
{KSFILTER_NODE, 0, KSFILTER_NODE, KSNODEPIN_STANDARD_IN}, //Transport pin -> Capture Filter pin 0 {KSFILTER_NODE, 0, KSFILTER_NODE, KSNODEPIN_STANDARD_IN}, //Transport pin -> Capture Filter pin 0
}; };
/*****************************************************************************************/ /*****************************************************************************************/
//Define the Filter Factory Descriptor for the filter //Define the Filter Factory Descriptor for the filter
//This structure brings together all of the structures that define //This structure brings together all of the structures that define
//the tuner filter as it appears when it is first instantiated. //the tuner filter as it appears when it is first instantiated.
//Note that not all of the template pin and node types may be exposed as //Note that not all of the template pin and node types may be exposed as
//pin and node factories when the filter is first instanciated. //pin and node factories when the filter is first instanciated.
//The KSFILTER_DESCRIPTOR structure describes the characteristics of a filter created by a given filter factory. //The KSFILTER_DESCRIPTOR structure describes the characteristics of a filter created by a given filter factory.
DEFINE_KSFILTER_DESCRIPTOR(SkyWalker1CaptureFilterDescriptor) DEFINE_KSFILTER_DESCRIPTOR(SkyWalker1CaptureFilterDescriptor)
{ {
&SkyWalker1CaptureDispatchTable, //Dispatch (Filter Specific Driver) &SkyWalker1CaptureDispatchTable, //Dispatch (Filter Specific Driver)
NULL, //AutomationTable NULL, //AutomationTable
KSFILTER_DESCRIPTOR_VERSION, //Version KSFILTER_DESCRIPTOR_VERSION, //Version
0, //Flags 0, //Flags
&SKYWALKER_CAPTURE_FILTER, //ReferenceGuid &SKYWALKER_CAPTURE_FILTER, //ReferenceGuid
DEFINE_KSFILTER_PIN_DESCRIPTORS(SkyWalker1CapturePinDescriptors), DEFINE_KSFILTER_PIN_DESCRIPTORS(SkyWalker1CapturePinDescriptors),
//PinDescriptorsCount; must expose at least one pin //PinDescriptorsCount; must expose at least one pin
//PinDescriptorSize; size of each item //PinDescriptorSize; size of each item
//PinDescriptors; table of pin descriptors //PinDescriptors; table of pin descriptors
DEFINE_KSFILTER_CATEGORY(KSCATEGORY_BDA_RECEIVER_COMPONENT), DEFINE_KSFILTER_CATEGORY(KSCATEGORY_BDA_RECEIVER_COMPONENT),
//CategoriesCount; number of categories in the table //CategoriesCount; number of categories in the table
//Categories; table of categories //Categories; table of categories
DEFINE_KSFILTER_NODE_DESCRIPTORS_NULL, DEFINE_KSFILTER_NODE_DESCRIPTORS_NULL,
//NodeDescriptorsCount; //NodeDescriptorsCount;
//NodeDescriptorSize; //NodeDescriptorSize;
//NodeDescriptors; //NodeDescriptors;
DEFINE_KSFILTER_CONNECTIONS(SkyWalker1CaptureConnections), DEFINE_KSFILTER_CONNECTIONS(SkyWalker1CaptureConnections),
//Automatically fills in the connections table for a filter which defines no explicit connections //Automatically fills in the connections table for a filter which defines no explicit connections
//ConnectionsCount; number of connections in the table //ConnectionsCount; number of connections in the table
//Connections; table of connections //Connections; table of connections
NULL //ComponentId; NULL //ComponentId;
}; };
//Array of BDA_PIN_PAIRING structures that are used to determine //Array of BDA_PIN_PAIRING structures that are used to determine
//which nodes get duplicated when more than one output pin type is //which nodes get duplicated when more than one output pin type is
//connected to a single input pin type or when more that one input pin //connected to a single input pin type or when more that one input pin
//type is connected to a single output pin type. //type is connected to a single output pin type.
// //
const BDA_PIN_PAIRING SkyWalker1CapturePinPairings[] = const BDA_PIN_PAIRING SkyWalker1CapturePinPairings[] =
{ {
//Input pin to Output pin Topology Joints //Input pin to Output pin Topology Joints
// //
{ {
0, //ulInputPin; 0 element in the TemplatePinDescriptors array. 0, //ulInputPin; 0 element in the TemplatePinDescriptors array.
1, //ulOutputPin; 1 element in the TemplatePinDescriptors array. 1, //ulOutputPin; 1 element in the TemplatePinDescriptors array.
1, //ulcMaxInputsPerOutput 1, //ulcMaxInputsPerOutput
1, //ulcMinInputsPerOutput 1, //ulcMinInputsPerOutput
1, //ulcMaxOutputsPerInput 1, //ulcMaxOutputsPerInput
1, //ulcMinOutputsPerInput 1, //ulcMinOutputsPerInput
0, //ulcTopologyJoints 0, //ulcTopologyJoints
NULL //pTopologyJoints; array of joints NULL //pTopologyJoints; array of joints
} }
//If applicable, list topology of joints between other pins. //If applicable, list topology of joints between other pins.
// //
}; };
//BDA_FILTER_TEMPLATE structure describes the template topology for BDA Driver //BDA_FILTER_TEMPLATE structure describes the template topology for BDA Driver
const BDA_FILTER_TEMPLATE SkyWalker1CaptureTemplate = const BDA_FILTER_TEMPLATE SkyWalker1CaptureTemplate =
{ {
&SkyWalker1CaptureFilterDescriptor,//Pointer to KS_FILTER_DESCRIPTOR which describes the Filter for BDA Device &SkyWalker1CaptureFilterDescriptor,//Pointer to KS_FILTER_DESCRIPTOR which describes the Filter for BDA Device
SIZEOF_ARRAY(SkyWalker1CapturePinPairings), //Number of PAIRS of pins in BDA_PIN_PAIRING Array SIZEOF_ARRAY(SkyWalker1CapturePinPairings), //Number of PAIRS of pins in BDA_PIN_PAIRING Array
SkyWalker1CapturePinPairings //Array of Pin Pairing describes topology between a pair of Filter's Input and Output Pins SkyWalker1CapturePinPairings //Array of Pin Pairing describes topology between a pair of Filter's Input and Output Pins
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */

View File

@ -1,142 +1,142 @@
; SkyWalker1Installer.INF -- This file installs SkyWalker1 Driver ; SkyWalker1Installer.INF -- This file installs SkyWalker1 Driver
; ;
[Version] [Version]
signature="$CHICAGO$" signature="$CHICAGO$"
Class=Media Class=Media
ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318} ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
Provider=%SGI% Provider=%SGI%
CatalogFile=SkyWalker1Installer.cat CatalogFile=SkyWalker1Installer.cat
DriverVer= 8/17/2009 DriverVer= 8/17/2009
; F i l e c o p y i n g s e c t i o n s (where the files go to). ; F i l e c o p y i n g s e c t i o n s (where the files go to).
; ;
[DestinationDirs] [DestinationDirs]
DefaultDestDir=10,system32\drivers DefaultDestDir=10,system32\drivers
[Manufacturer] [Manufacturer]
%SGI%=SGI %SGI%=SGI
[ControlFlags] [ControlFlags]
;ExcludeFromSelect=* ;ExcludeFromSelect=*
;ExcludeFromSelect.NT=* ;ExcludeFromSelect.NT=*
; =================== Generic ================================== ; =================== Generic ==================================
[SGI] [SGI]
%SkyWalker1.DeviceDesc%=Skywalker1.Device,USB\VID_09C0&PID_0203 ;SkyWalker1 %SkyWalker1.DeviceDesc%=Skywalker1.Device,USB\VID_09C0&PID_0203 ;SkyWalker1
[Skywalker1.Device] [Skywalker1.Device]
Include = ks.inf, kscaptur.inf, bda.inf Include = ks.inf, kscaptur.inf, bda.inf
needs = KS.Registration, KSCAPTUR.Registration, BDA.Installation needs = KS.Registration, KSCAPTUR.Registration, BDA.Installation
AddReg = Skywalker1.AddReg AddReg = Skywalker1.AddReg
CopyFiles = Skywalker1.CopyDrivers CopyFiles = Skywalker1.CopyDrivers
[Skywalker1.Device.NT] [Skywalker1.Device.NT]
Include = ks.inf, kscaptur.inf, bda.inf Include = ks.inf, kscaptur.inf, bda.inf
needs = KS.Registration.NT, KSCAPTUR.Registration.NT, BDA.Installation.NT needs = KS.Registration.NT, KSCAPTUR.Registration.NT, BDA.Installation.NT
;AddReg = Skywalker1.AddReg ;AddReg = Skywalker1.AddReg
CopyFiles = Skywalker1.CopyDrivers CopyFiles = Skywalker1.CopyDrivers
; KnownFiles = Skywalker1.KnownFiles ; KnownFiles = Skywalker1.KnownFiles
[Skywalker1.Device.NT.Services] [Skywalker1.Device.NT.Services]
Addservice=SkyWalker1TVTuner, 0x00000002, Skywalker1.AddService Addservice=SkyWalker1TVTuner, 0x00000002, Skywalker1.AddService
[Skywalker1.AddService] [Skywalker1.AddService]
DisplayName=%SkyWalker1.FriendlyName% DisplayName=%SkyWalker1.FriendlyName%
ServiceType=1 ; SERVICE_KERNEL_DRIVER ServiceType=1 ; SERVICE_KERNEL_DRIVER
StartType=3 ; SERVICE_DEMAND_START StartType=3 ; SERVICE_DEMAND_START
ErrorControl=1 ; SERVICE_ERROR_NORMAL ErrorControl=1 ; SERVICE_ERROR_NORMAL
ServiceBinary=%10%\System32\Drivers\SkyWalker1TVTuner.sys ServiceBinary=%10%\System32\Drivers\SkyWalker1TVTuner.sys
LoadOrderGroup=ExtendedBase LoadOrderGroup=ExtendedBase
[Skywalker1.CopyDrivers] [Skywalker1.CopyDrivers]
SkyWalker1TVTuner.sys SkyWalker1TVTuner.sys
[Skywalker1.AddReg] [Skywalker1.AddReg]
HKR,,DevLoader,,*NTKERN HKR,,DevLoader,,*NTKERN
HKR,,NTMPDriver,,SkyWalker1TVTuner.sys HKR,,NTMPDriver,,SkyWalker1TVTuner.sys
HKR,,PageOutWhenUnopened,3,01 HKR,,PageOutWhenUnopened,3,01
[Skywalker1.Device.Interfaces] [Skywalker1.Device.Interfaces]
AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,Skywalker1.Receiver.Interfaces AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,Skywalker1.Receiver.Interfaces
AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,Skywalker1.Tuner.Interfaces AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,Skywalker1.Tuner.Interfaces
[Skywalker1.Device.NT.Interfaces] [Skywalker1.Device.NT.Interfaces]
AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,Skywalker1.Receiver.Interfaces AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,Skywalker1.Receiver.Interfaces
AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,Skywalker1.Tuner.Interfaces AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,Skywalker1.Tuner.Interfaces
[Skywalker1.Tuner.Interfaces] [Skywalker1.Tuner.Interfaces]
AddReg=Skywalker1.Tuner.Interfaces.AddReg AddReg=Skywalker1.Tuner.Interfaces.AddReg
[Skywalker1.Tuner.Interfaces.AddReg] [Skywalker1.Tuner.Interfaces.AddReg]
HKR,,CLSID,,%KSProxy.CLSID% HKR,,CLSID,,%KSProxy.CLSID%
HKR,,FriendlyName,,%SkyWalker1.Tuner.FriendlyName% HKR,,FriendlyName,,%SkyWalker1.Tuner.FriendlyName%
[Skywalker1.Receiver.Interfaces] [Skywalker1.Receiver.Interfaces]
AddReg=Skywalker1.Receiver.Interfaces.AddReg AddReg=Skywalker1.Receiver.Interfaces.AddReg
[Skywalker1.Receiver.Interfaces.AddReg] [Skywalker1.Receiver.Interfaces.AddReg]
HKR,,CLSID,,%KSProxy.CLSID% HKR,,CLSID,,%KSProxy.CLSID%
HKR,,FriendlyName,,%SkyWalker1.Receiver.FriendlyName% HKR,,FriendlyName,,%SkyWalker1.Receiver.FriendlyName%
[Strings] [Strings]
;non-localizable ;non-localizable
SGI="Plethorasoft" SGI="Plethorasoft"
MfgName="SGI" MfgName="SGI"
SkyWalker1.DeviceDesc="SkyWalker1 BDA TVTuner" SkyWalker1.DeviceDesc="SkyWalker1 BDA TVTuner"
SkyWalker1.Tuner.FriendlyName="SkyWalker1 TV Tuner" SkyWalker1.Tuner.FriendlyName="SkyWalker1 TV Tuner"
SkyWalker1.Receiver.FriendlyName="SkyWalker1 TV Receiver" SkyWalker1.Receiver.FriendlyName="SkyWalker1 TV Receiver"
SkyWalker1.Tuner="SkyWalker1.Tuner" SkyWalker1.Tuner="SkyWalker1.Tuner"
KSProxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}" KSProxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
KSCATEGORY_BDA_NETWORK_TUNER="{71985F48-1CA1-11d3-9CC8-00C04F7971E0}" KSCATEGORY_BDA_NETWORK_TUNER="{71985F48-1CA1-11d3-9CC8-00C04F7971E0}"
KSCATEGORY_BDA_RECEIVER_COMPONENT="{FD0A5AF4-B41D-11d2-9C95-00C04F7971E0}" KSCATEGORY_BDA_RECEIVER_COMPONENT="{FD0A5AF4-B41D-11d2-9C95-00C04F7971E0}"
SKYWALKER_TUNER="{5C4E764F-AB43-46A9-B21E-8529C70F0A23}" SKYWALKER_TUNER="{5C4E764F-AB43-46A9-B21E-8529C70F0A23}"
SKYWALKER_CAPTURE="{0F8F74D9-E524-4D05-BB60-F0C69ACB1756}" SKYWALKER_CAPTURE="{0F8F74D9-E524-4D05-BB60-F0C69ACB1756}"
; ;
; ServiceType values ; ServiceType values
SERVICE_KERNEL_DRIVER = 0x00000001 SERVICE_KERNEL_DRIVER = 0x00000001
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002 SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
SERVICE_ADAPTER = 0x00000004 SERVICE_ADAPTER = 0x00000004
SERVICE_RECOGNIZER_DRIVER = 0x00000008 SERVICE_RECOGNIZER_DRIVER = 0x00000008
SERVICE_WIN32_OWN_PROCESS = 0x00000010 SERVICE_WIN32_OWN_PROCESS = 0x00000010
SERVICE_WIN32_SHARE_PROCESS = 0x00000020 SERVICE_WIN32_SHARE_PROCESS = 0x00000020
SERVICE_INTERACTIVE_PROCESS = 0x00000100 SERVICE_INTERACTIVE_PROCESS = 0x00000100
SERVICE_INTERACTIVE_SHARE_PROCESS = 0x00000120 SERVICE_INTERACTIVE_SHARE_PROCESS = 0x00000120
; StartType values ; StartType values
SERVICE_BOOT_START = 0x00000000 SERVICE_BOOT_START = 0x00000000
SERVICE_SYSTEM_START = 0x00000001 SERVICE_SYSTEM_START = 0x00000001
SERVICE_AUTO_START = 0x00000002 SERVICE_AUTO_START = 0x00000002
SERVICE_DEMAND_START = 0x00000003 SERVICE_DEMAND_START = 0x00000003
SERVICE_DISABLED = 0x00000004 SERVICE_DISABLED = 0x00000004
; ErrorControl values ; ErrorControl values
SERVICE_ERROR_IGNORE = 0x00000000 SERVICE_ERROR_IGNORE = 0x00000000
SERVICE_ERROR_NORMAL = 0x00000001 SERVICE_ERROR_NORMAL = 0x00000001
SERVICE_ERROR_SEVERE = 0x00000002 SERVICE_ERROR_SEVERE = 0x00000002
SERVICE_ERROR_CRITICAL = 0x00000003 SERVICE_ERROR_CRITICAL = 0x00000003
; Characteristic flags ; Characteristic flags
NCF_VIRTUAL = 0x0001 NCF_VIRTUAL = 0x0001
NCF_WRAPPER = 0x0002 NCF_WRAPPER = 0x0002
NCF_PHYSICAL = 0x0004 NCF_PHYSICAL = 0x0004
NCF_HIDDEN = 0x0008 NCF_HIDDEN = 0x0008
NCF_NO_SERVICE = 0x0010 NCF_NO_SERVICE = 0x0010
NCF_NOT_USER_REMOVABLE = 0x0020 NCF_NOT_USER_REMOVABLE = 0x0020
NCF_HAS_UI = 0x0080 NCF_HAS_UI = 0x0080
NCF_MODEM = 0x0100 NCF_MODEM = 0x0100
; Registry types ; Registry types
REG_MULTI_SZ = 0x10000 REG_MULTI_SZ = 0x10000
REG_EXPAND_SZ = 0x20000 REG_EXPAND_SZ = 0x20000
REG_DWORD = 0x10001 REG_DWORD = 0x10001
; Win9x Compatible Types ; Win9x Compatible Types
REG_BINARY = 17 REG_BINARY = 17
REG_SZ = 0 REG_SZ = 0
; Service install flags ; Service install flags
SPSVCINST_TAGTOFRONT = 0x1 SPSVCINST_TAGTOFRONT = 0x1
SPSVCINST_ASSOCSERVICE = 0x2 SPSVCINST_ASSOCSERVICE = 0x2

View File

@ -1,137 +1,137 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1Main.cpp File Name : SkyWalker1Main.cpp
Author : Author :
Date : Date :
Purpose : This file contains the Entry Point of the Device Driver. Purpose : This file contains the Entry Point of the Device Driver.
The File also defines various Dispatch Routine pointers The File also defines various Dispatch Routine pointers
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1Main.h" //Common For all the Definitions, #include "SkyWalker1Main.h" //Common For all the Definitions,
//Declarations and Library Routines //Declarations and Library Routines
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
//Device Dispatch Table : Lists the dispatch routines for the //Device Dispatch Table : Lists the dispatch routines for the
//major events in the life of Device //major events in the life of Device
const KSDEVICE_DISPATCH SkyWalker1DispatchTable = { const KSDEVICE_DISPATCH SkyWalker1DispatchTable = {
/* Add */ SkyWalker1AddDevice, /* Add */ SkyWalker1AddDevice,
/* Start */ SkyWalker1Start, /* Start */ SkyWalker1Start,
/* PostStart */ NULL, /* PostStart */ NULL,
/* QueryStop */ SkyWalker1QueryStop, /* QueryStop */ SkyWalker1QueryStop,
/* CancelStop */ NULL, /* CancelStop */ NULL,
/* Stop */ SkyWalker1Stop, /* Stop */ SkyWalker1Stop,
/* QueryRemove */ NULL, /*QueryRemoveUsbDevice,*/ /* QueryRemove */ NULL, /*QueryRemoveUsbDevice,*/
/* CancelRemove */ NULL, /* CancelRemove */ NULL,
/* Remove */ SkyWalker1Remove, /* Remove */ SkyWalker1Remove,
/* QueryCapabilities */ NULL, /* QueryCapabilities */ NULL,
/* SurpriseRemoval */ NULL, /* SurpriseRemoval */ NULL,
/* QueryPower */ NULL, /* QueryPower */ NULL,
/* SetPower */ SkyWalker1SetPower /* SetPower */ SkyWalker1SetPower
}; };
//Array of Filter Descriptors supported by the Current Driver //Array of Filter Descriptors supported by the Current Driver
// Hold all the filter descriptors in an array // Hold all the filter descriptors in an array
DEFINE_KSFILTER_DESCRIPTOR_TABLE(FilterDescriptors) DEFINE_KSFILTER_DESCRIPTOR_TABLE(FilterDescriptors)
{ {
&SkyWalker1CaptureFilterDescriptor //Only Capture filter is a Kernel Streaming Filter &SkyWalker1CaptureFilterDescriptor //Only Capture filter is a Kernel Streaming Filter
}; };
//Device Descriptor : It Describes the Device with all it's dispatch //Device Descriptor : It Describes the Device with all it's dispatch
//functions and Filters //functions and Filters
const KSDEVICE_DESCRIPTOR SkyWalker1DeviceDescriptor = const KSDEVICE_DESCRIPTOR SkyWalker1DeviceDescriptor =
{ {
&SkyWalker1DispatchTable, &SkyWalker1DispatchTable,
SIZEOF_ARRAY(FilterDescriptors), //Filter Descriptor Count SIZEOF_ARRAY(FilterDescriptors), //Filter Descriptor Count
FilterDescriptors, //Filter Descriptor Table FilterDescriptors, //Filter Descriptor Table
KSDEVICE_DESCRIPTOR_VERSION KSDEVICE_DESCRIPTOR_VERSION
}; };
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
/***************************************************************************** /*****************************************************************************
Function : DriverEntry Function : DriverEntry
Description : This is a Entry Point function of the Windows Device Driver Description : This is a Entry Point function of the Windows Device Driver
It defines various dispatch routine Entry Point for the Driver It defines various dispatch routine Entry Point for the Driver
IN PARAM : <PDRIVER_OBJECT > Pointer to Driver Object which is called IN PARAM : <PDRIVER_OBJECT > Pointer to Driver Object which is called
<PUNICODE_STRING> Pointer to the Registry Entry of the Driver <PUNICODE_STRING> Pointer to the Registry Entry of the Driver
OUT PARAM : <NTSTATUS> Status of the Driver Entry routine OUT PARAM : <NTSTATUS> Status of the Driver Entry routine
STATUS_SUCCESS always STATUS_SUCCESS always
PreCondition : Driver is Unloaded PreCondition : Driver is Unloaded
PostCondtion : Driver is Loaded with various Entry Point defined PostCondtion : Driver is Loaded with various Entry Point defined
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath) IN PUNICODE_STRING pRegistryPath)
{ {
NTSTATUS ntEntryStatus = STATUS_SUCCESS; NTSTATUS ntEntryStatus = STATUS_SUCCESS;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
SkyWalkerDebugPrint(ENTRY_LEVEL, ("SkyWalker1 Driver Compiled on Date = %s, Time = %s\n",__DATE__,__TIME__)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("SkyWalker1 Driver Compiled on Date = %s, Time = %s\n",__DATE__,__TIME__));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("Debug Level = %u\n",nCurrentDebugLevel)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("Debug Level = %u\n",nCurrentDebugLevel));
//As this is an AVStream Minidriver it should call the KsInitializeDriver() //As this is an AVStream Minidriver it should call the KsInitializeDriver()
ntEntryStatus = KsInitializeDriver( ntEntryStatus = KsInitializeDriver(
pDriverObject, pDriverObject,
pRegistryPath, pRegistryPath,
&SkyWalker1DeviceDescriptor); &SkyWalker1DeviceDescriptor);
PrintFunctionExit(__FUNCTION__,ntEntryStatus); PrintFunctionExit(__FUNCTION__,ntEntryStatus);
return ntEntryStatus; return ntEntryStatus;
} }
/***************************************************************************** /*****************************************************************************
Function : SkyWalker1DriverUnload Function : SkyWalker1DriverUnload
Description : This is a Exit Point function of the Windows Device Driver Description : This is a Exit Point function of the Windows Device Driver
It does not usedful job for the PnP Driver but required to It does not usedful job for the PnP Driver but required to
unload the Driver from the Running System. unload the Driver from the Running System.
IN PARAM : <PDRIVER_OBJECT > Pointer to Driver Object which is to be Unloaded IN PARAM : <PDRIVER_OBJECT > Pointer to Driver Object which is to be Unloaded
OUT PARAM : NONE OUT PARAM : NONE
PreCondition : Driver is Loaded PreCondition : Driver is Loaded
PostCondtion : Driver is Unloaded PostCondtion : Driver is Unloaded
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
VOID SkyWalker1DriverUnload(PDRIVER_OBJECT pDriverObject) VOID SkyWalker1DriverUnload(PDRIVER_OBJECT pDriverObject)
{ {
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
//No Processing //No Processing
PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS); PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS);
} }

View File

@ -1,336 +1,336 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1PnP.cpp File Name : SkyWalker1PnP.cpp
Author : Author :
Date : Date :
Purpose : PnP IRP Message Handler Purpose : PnP IRP Message Handler
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1Main.h" //Common For all the Definitions, #include "SkyWalker1Main.h" //Common For all the Definitions,
//Declarations and Library Routines //Declarations and Library Routines
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
void PrintKSDeviceObject(IN PKSDEVICE pKSDeviceObject); void PrintKSDeviceObject(IN PKSDEVICE pKSDeviceObject);
/* End of Function prototype definitions */ /* End of Function prototype definitions */
/***************************************************************************** /*****************************************************************************
Function : SkyWalker1AddDevice Function : SkyWalker1AddDevice
Description : This Function is called by the PnP Manager for each Device Description : This Function is called by the PnP Manager for each Device
managed by the Driver.It is called during the System Initialization managed by the Driver.It is called during the System Initialization
and any time a new Device is enumerated while the System is running. and any time a new Device is enumerated while the System is running.
IN PARAM : <PKSDEVICE > Pointer to the Enumerated Physical Device IN PARAM : <PKSDEVICE > Pointer to the Enumerated Physical Device
KSDEVICE is a WDM Functional Device which is managed by the AVStream KSDEVICE is a WDM Functional Device which is managed by the AVStream
OUT PARAM : <NTSTATUS> Status of the Device Addition OUT PARAM : <NTSTATUS> Status of the Device Addition
STATUS_SUCCESS when the Device added to the System STATUS_SUCCESS when the Device added to the System
Reason for Failure incase of Error Reason for Failure incase of Error
PreCondition : Driver is Loaded without Functional/ Filter Device Objects PreCondition : Driver is Loaded without Functional/ Filter Device Objects
PostCondtion : Functional Device Object [FDO] or Filter Device Object [FiDO] are created PostCondtion : Functional Device Object [FDO] or Filter Device Object [FiDO] are created
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : AddDevice is Must for the PnP Drivers Note : AddDevice is Must for the PnP Drivers
This routine runs at PASSIVE_LEVEL_IRQL This routine runs at PASSIVE_LEVEL_IRQL
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS SkyWalker1AddDevice(IN PKSDEVICE pKSDeviceObject) NTSTATUS SkyWalker1AddDevice(IN PKSDEVICE pKSDeviceObject)
{ {
NTSTATUS ntAddDeviceStatus = STATUS_SUCCESS; NTSTATUS ntAddDeviceStatus = STATUS_SUCCESS;
PKSFILTERFACTORY pFilterFactory = NULL; PKSFILTERFACTORY pFilterFactory = NULL;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
PrintKSDeviceObject(pKSDeviceObject); PrintKSDeviceObject(pKSDeviceObject);
if(!IS_VALID(pKSDeviceObject)) if(!IS_VALID(pKSDeviceObject))
{ {
SkyWalkerDebugPrint(ENTRY_LEVEL,("Invalid KS Device Object Received\n")); SkyWalkerDebugPrint(ENTRY_LEVEL,("Invalid KS Device Object Received\n"));
ntAddDeviceStatus = STATUS_UNSUCCESSFUL; ntAddDeviceStatus = STATUS_UNSUCCESSFUL;
goto FinishAddDevice; goto FinishAddDevice;
} }
//Allcate Memory for the SkyWalker1 Device //Allcate Memory for the SkyWalker1 Device
CSkyWalker1Device * pDevice = new(NonPagedPool,TUNER_MEM_TAG)CSkyWalker1Device; CSkyWalker1Device * pDevice = new(NonPagedPool,TUNER_MEM_TAG)CSkyWalker1Device;
if(!IS_VALID(pDevice)) if(!IS_VALID(pDevice))
{ {
SkyWalkerDebugPrint(ENTRY_LEVEL,("Can not allocate Memory for the SkyWalker1 Device\n")); SkyWalkerDebugPrint(ENTRY_LEVEL,("Can not allocate Memory for the SkyWalker1 Device\n"));
ntAddDeviceStatus = STATUS_INSUFFICIENT_RESOURCES; ntAddDeviceStatus = STATUS_INSUFFICIENT_RESOURCES;
goto FinishAddDevice; goto FinishAddDevice;
} }
ntAddDeviceStatus = pDevice->Create(pKSDeviceObject); ntAddDeviceStatus = pDevice->Create(pKSDeviceObject);
PrintKSDeviceObject(pKSDeviceObject); PrintKSDeviceObject(pKSDeviceObject);
FinishAddDevice: FinishAddDevice:
PrintFunctionExit(__FUNCTION__,ntAddDeviceStatus); PrintFunctionExit(__FUNCTION__,ntAddDeviceStatus);
return ntAddDeviceStatus; return ntAddDeviceStatus;
} }
/***************************************************************************** /*****************************************************************************
Function : SkyWalker1Remove Function : SkyWalker1Remove
Description : This function is called when the IRP_MN_REMOVE_DEVICE is sent Description : This function is called when the IRP_MN_REMOVE_DEVICE is sent
by the PnP Manager during Device Removal by the PnP Manager during Device Removal
IN PARAM : <PKSDEVICE > Pointer to the Enumerated Physical Device IN PARAM : <PKSDEVICE > Pointer to the Enumerated Physical Device
KSDEVICE is a WDM Functional Device which is managed by the AVStream KSDEVICE is a WDM Functional Device which is managed by the AVStream
<PIRP> Remove Device Io Request Packet <PIRP> Remove Device Io Request Packet
OUT PARAM : NONE OUT PARAM : NONE
PreCondition : Started Device PreCondition : Started Device
PostCondtion : Device Removed PostCondtion : Device Removed
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
VOID SkyWalker1Remove( IN PKSDEVICE pKSDeviceObject, VOID SkyWalker1Remove( IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket) IN PIRP pIoRequestPacket)
{ {
NTSTATUS ntDeviceRemoveStatus = STATUS_SUCCESS; NTSTATUS ntDeviceRemoveStatus = STATUS_SUCCESS;
CSkyWalker1Device * pDevice = NULL; CSkyWalker1Device * pDevice = NULL;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
//Get the SkyWalker1 Device Object from the Context Info. //Get the SkyWalker1 Device Object from the Context Info.
pDevice = reinterpret_cast<CSkyWalker1Device *>(pKSDeviceObject->Context); pDevice = reinterpret_cast<CSkyWalker1Device *>(pKSDeviceObject->Context);
if(!IS_VALID(pDevice)) if(!IS_VALID(pDevice))
{ {
//Unexpected Remove for the Device //Unexpected Remove for the Device
SkyWalkerDebugPrint(ENTRY_LEVEL,("No Connection found with SkyWalker Device\n")); SkyWalkerDebugPrint(ENTRY_LEVEL,("No Connection found with SkyWalker Device\n"));
ntDeviceRemoveStatus = STATUS_UNSUCCESSFUL; ntDeviceRemoveStatus = STATUS_UNSUCCESSFUL;
goto ExitRemoveDevice; goto ExitRemoveDevice;
} }
ntDeviceRemoveStatus = pDevice->Close(pKSDeviceObject,pIoRequestPacket); ntDeviceRemoveStatus = pDevice->Close(pKSDeviceObject,pIoRequestPacket);
//Deallocate the SkyWalker1 Device Object Memory //Deallocate the SkyWalker1 Device Object Memory
delete pDevice; delete pDevice;
//Remove Reference of the SkyWalker1 Device from the KS Object //Remove Reference of the SkyWalker1 Device from the KS Object
pKSDeviceObject->Context = NULL; pKSDeviceObject->Context = NULL;
ExitRemoveDevice: ExitRemoveDevice:
PrintFunctionExit(__FUNCTION__,ntDeviceRemoveStatus); PrintFunctionExit(__FUNCTION__,ntDeviceRemoveStatus);
} }
/***************************************************************************** /*****************************************************************************
Function : SkyWalker1Start Function : SkyWalker1Start
Description : This function is called when the IRP_MN_START_DEVICE is sent Description : This function is called when the IRP_MN_START_DEVICE is sent
by the PnP Manager after Allocating Resources to the Device. by the PnP Manager after Allocating Resources to the Device.
IRP_MN_START_DEVICE is called once for each device created from IRP_MN_START_DEVICE is called once for each device created from
the Driver using the IoCreateDevice() call. the Driver using the IoCreateDevice() call.
When BDA Device Starts operating Pnp Dispatches the IRP_MN_START_DEVICE to the ks.sys When BDA Device Starts operating Pnp Dispatches the IRP_MN_START_DEVICE to the ks.sys
AvStream class Driver inturn calls the start routine of the BDA minidriver AvStream class Driver inturn calls the start routine of the BDA minidriver
associated with the BDA Device. This Start Routine retrives information about the associated with the BDA Device. This Start Routine retrives information about the
device from the registry, sets information about the Device and then calls the device from the registry, sets information about the Device and then calls the
BdaCreateFilterFactory() support function to BdaCreateFilterFactory() support function to
1) Create Filter Factory from the Initial Filter Descriptor (KSFILTER_DESCRIPTOR) 1) Create Filter Factory from the Initial Filter Descriptor (KSFILTER_DESCRIPTOR)
for the Device.The Initial Filter Descriptor references Dispatch and Automation for the Device.The Initial Filter Descriptor references Dispatch and Automation
tables for the Filter and Input Pins tables for the Filter and Input Pins
2) Associate Filter Factory with the BDA_FILTER_TEMPLATE structure.This structure 2) Associate Filter Factory with the BDA_FILTER_TEMPLATE structure.This structure
references template filter descriptor for the Device and the list of possible references template filter descriptor for the Device and the list of possible
pairs of the input and output pins.The Descriptor and list inturn reference. pairs of the input and output pins.The Descriptor and list inturn reference.
a) Static Template Structure that can be used by Network Provider to determine a) Static Template Structure that can be used by Network Provider to determine
BDA Driver topology BDA Driver topology
b) Static Template Structure that can be used by Network Provider to manipulate b) Static Template Structure that can be used by Network Provider to manipulate
BDA Filter BDA Filter
c) Nodes and Pins for a BDA Filter along with possible ways to connect the Filter c) Nodes and Pins for a BDA Filter along with possible ways to connect the Filter
d) Routines that a Netwrok provider can use to Create and Close a Filter instance d) Routines that a Netwrok provider can use to Create and Close a Filter instance
3) Register the Static Template structures that are specified by BDA_FILTER_TEMPLATE 3) Register the Static Template structures that are specified by BDA_FILTER_TEMPLATE
with the BDA support library so that the library can provide default handling with the BDA support library so that the library can provide default handling
for a BDA MiniDriver's Properties and methods. for a BDA MiniDriver's Properties and methods.
IN PARAM : <PKSDEVICE> Reference to Device to be Started IN PARAM : <PKSDEVICE> Reference to Device to be Started
<PIRP> IoRequest Packet <PIRP> IoRequest Packet
OUT PARAM : <NTSTATUS> Status of the Tuner Start OUT PARAM : <NTSTATUS> Status of the Tuner Start
STATUS_SUCCESS in case of successful execution STATUS_SUCCESS in case of successful execution
Failure Code in other cases Failure Code in other cases
PreCondition : Stopped Device or Device Enumerated for the First Time PreCondition : Stopped Device or Device Enumerated for the First Time
PostCondtion : Device Initialized with the Newly allocated Resources, PostCondtion : Device Initialized with the Newly allocated Resources,
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : This is called from the PASSIVE_LEVEL_IRQL Note : This is called from the PASSIVE_LEVEL_IRQL
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS SkyWalker1Start(IN PKSDEVICE pKSDeviceObject, NTSTATUS SkyWalker1Start(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PCM_RESOURCE_LIST pResourceList, IN PCM_RESOURCE_LIST pResourceList,
IN PCM_RESOURCE_LIST pResourceListTranslated) IN PCM_RESOURCE_LIST pResourceListTranslated)
{ {
NTSTATUS ntStartStatus = STATUS_SUCCESS; NTSTATUS ntStartStatus = STATUS_SUCCESS;
CSkyWalker1Device * pDevice = NULL; CSkyWalker1Device * pDevice = NULL;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
//Get the SkyWalker1 Device Object from the Context Info. //Get the SkyWalker1 Device Object from the Context Info.
pDevice = reinterpret_cast<CSkyWalker1Device *>(pKSDeviceObject->Context); pDevice = reinterpret_cast<CSkyWalker1Device *>(pKSDeviceObject->Context);
if(!IS_VALID(pDevice)) if(!IS_VALID(pDevice))
{ {
//No Device Found //No Device Found
SkyWalkerDebugPrint(ENTRY_LEVEL,("No Connection with SkyWalker Device\n")); SkyWalkerDebugPrint(ENTRY_LEVEL,("No Connection with SkyWalker Device\n"));
ntStartStatus = STATUS_UNSUCCESSFUL; ntStartStatus = STATUS_UNSUCCESSFUL;
goto ExitStartDevice; goto ExitStartDevice;
} }
//Call the Start device function of the SkyWalker1 Device class //Call the Start device function of the SkyWalker1 Device class
ntStartStatus = pDevice->Start( pKSDeviceObject, ntStartStatus = pDevice->Start( pKSDeviceObject,
pIoRequestPacket, pIoRequestPacket,
pResourceList, pResourceList,
pResourceListTranslated); pResourceListTranslated);
ExitStartDevice: ExitStartDevice:
PrintFunctionExit(__FUNCTION__,ntStartStatus); PrintFunctionExit(__FUNCTION__,ntStartStatus);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
Function : SkyWalker1Stop Function : SkyWalker1Stop
Description : This function is called when the IRP_MN_STOP_DEVICE is sent Description : This function is called when the IRP_MN_STOP_DEVICE is sent
by the PnP Manager during Device Removal by the PnP Manager during Device Removal
IN PARAM : <PKSDEVICE> Reference to Device to be Removed IN PARAM : <PKSDEVICE> Reference to Device to be Removed
<PIRP> Stop Device Io Request Packet <PIRP> Stop Device Io Request Packet
OUT PARAM : NONE OUT PARAM : NONE
PreCondition : Started Device PreCondition : Started Device
PostCondtion : Device Stopped PostCondtion : Device Stopped
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
VOID SkyWalker1Stop(IN PKSDEVICE pKSDeviceObject, VOID SkyWalker1Stop(IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket) IN PIRP pIoRequestPacket)
{ {
NTSTATUS ntStopStatus = STATUS_SUCCESS; NTSTATUS ntStopStatus = STATUS_SUCCESS;
CSkyWalker1Device * pDevice = NULL; CSkyWalker1Device * pDevice = NULL;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
//Get the SkyWalker1 Device Object from the Context Info. //Get the SkyWalker1 Device Object from the Context Info.
pDevice = reinterpret_cast<CSkyWalker1Device *>(pKSDeviceObject->Context); pDevice = reinterpret_cast<CSkyWalker1Device *>(pKSDeviceObject->Context);
if(!IS_VALID(pDevice)) if(!IS_VALID(pDevice))
{ {
SkyWalkerDebugPrint(ENTRY_LEVEL,("No Connection with SkyWalker Device\n")); SkyWalkerDebugPrint(ENTRY_LEVEL,("No Connection with SkyWalker Device\n"));
goto ExitStopDevice; goto ExitStopDevice;
} }
//Call the Stop device function of the SkyWalker1 Device class //Call the Stop device function of the SkyWalker1 Device class
ntStopStatus = pDevice->Stop( pKSDeviceObject, ntStopStatus = pDevice->Stop( pKSDeviceObject,
pIoRequestPacket pIoRequestPacket
); );
ExitStopDevice: ExitStopDevice:
PrintFunctionExit(__FUNCTION__,ntStopStatus); PrintFunctionExit(__FUNCTION__,ntStopStatus);
} }
/***************************************************************************** /*****************************************************************************
Function : SkyWalker1QueryStop Function : SkyWalker1QueryStop
Description : This function is called when the IRP_MN_QUERY_STOP_DEVICE is sent Description : This function is called when the IRP_MN_QUERY_STOP_DEVICE is sent
by the PnP Manager during Device Stop by the PnP Manager during Device Stop
IN PARAM : <PKSDEVICE > Pointer to the Enumerated Physical Device IN PARAM : <PKSDEVICE > Pointer to the Enumerated Physical Device
KSDEVICE is a WDM Functional Device which is managed by the AVStream KSDEVICE is a WDM Functional Device which is managed by the AVStream
<PIRP> Remove Device Io Request Packet <PIRP> Remove Device Io Request Packet
OUT PARAM : NONE OUT PARAM : NONE
PreCondition : Started Device PreCondition : Started Device
PostCondtion : Query for stopping device is returned PostCondtion : Query for stopping device is returned
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : All the Devices created by the Driver are connected with Each other Note : All the Devices created by the Driver are connected with Each other
with the NextDevice Member of the Device Object with the NextDevice Member of the Device Object
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS SkyWalker1QueryStop( IN PKSDEVICE pKSDeviceObject, NTSTATUS SkyWalker1QueryStop( IN PKSDEVICE pKSDeviceObject,
IN PIRP pIoRequestPacket) IN PIRP pIoRequestPacket)
{ {
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS); PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
/***************************************************************************** /*****************************************************************************
Function : SkyWalker1SetPower Function : SkyWalker1SetPower
Description : This function is called when the IRP_MJ_POWER is sent Description : This function is called when the IRP_MJ_POWER is sent
by the PnP Manager during Power Management by the PnP Manager during Power Management
IN PARAM : <PKSDEVICE > Pointer to the Enumerated Physical Device IN PARAM : <PKSDEVICE > Pointer to the Enumerated Physical Device
KSDEVICE is a WDM Functional Device which is managed by the AVStream KSDEVICE is a WDM Functional Device which is managed by the AVStream
<PIRP> Power Device Io Request Packet <PIRP> Power Device Io Request Packet
OUT PARAM : NONE OUT PARAM : NONE
PreCondition : Started Device PreCondition : Started Device
PostCondtion : Query for stopping device is returned PostCondtion : Query for stopping device is returned
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : All the Devices created by the Driver are connected with Each other Note : All the Devices created by the Driver are connected with Each other
with the NextDevice Member of the Device Object with the NextDevice Member of the Device Object
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
VOID SkyWalker1SetPower VOID SkyWalker1SetPower
( (
IN PKSDEVICE pKSDeviceObject, //Pointer to the device object IN PKSDEVICE pKSDeviceObject, //Pointer to the device object
//provided by the system. //provided by the system.
IN PIRP pIoRequestPacket,//Pointer to the IRP related to this request. IN PIRP pIoRequestPacket,//Pointer to the IRP related to this request.
IN DEVICE_POWER_STATE To, //Requested power state. IN DEVICE_POWER_STATE To, //Requested power state.
IN DEVICE_POWER_STATE From //Current power state. IN DEVICE_POWER_STATE From //Current power state.
) )
{ {
CSkyWalker1Device * pDevice = NULL; CSkyWalker1Device * pDevice = NULL;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
//Get the SkyWalker1 Device Object from the Context Info. //Get the SkyWalker1 Device Object from the Context Info.
pDevice = reinterpret_cast<CSkyWalker1Device *>(pKSDeviceObject->Context); pDevice = reinterpret_cast<CSkyWalker1Device *>(pKSDeviceObject->Context);
if(!IS_VALID(pDevice)) if(!IS_VALID(pDevice))
{ {
SkyWalkerDebugPrint(ENTRY_LEVEL,("No Connection with SkyWalker Device\n")); SkyWalkerDebugPrint(ENTRY_LEVEL,("No Connection with SkyWalker Device\n"));
goto ExitSetPower; goto ExitSetPower;
} }
//Call the Set Power device function of the SkyWalker1 Device class //Call the Set Power device function of the SkyWalker1 Device class
pDevice->SetPower( pKSDeviceObject, pDevice->SetPower( pKSDeviceObject,
pIoRequestPacket, pIoRequestPacket,
To, To,
From From
); );
ExitSetPower: ExitSetPower:
PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS); PrintFunctionExit(__FUNCTION__,STATUS_SUCCESS);
} }
void PrintKSDeviceObject(IN PKSDEVICE pKSDeviceObject) void PrintKSDeviceObject(IN PKSDEVICE pKSDeviceObject)
{ {
SkyWalkerDebugPrint(ENTRY_LEVEL, (__FUNCTION__"\n")); SkyWalkerDebugPrint(ENTRY_LEVEL, (__FUNCTION__"\n"));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor = 0x%p \n",pKSDeviceObject->Descriptor)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor = 0x%p \n",pKSDeviceObject->Descriptor));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor->Dispatch = 0x%p \n",pKSDeviceObject->Descriptor->Dispatch)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor->Dispatch = 0x%p \n",pKSDeviceObject->Descriptor->Dispatch));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor->FilterDescriptorsCount = %lu \n",pKSDeviceObject->Descriptor->FilterDescriptorsCount)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor->FilterDescriptorsCount = %lu \n",pKSDeviceObject->Descriptor->FilterDescriptorsCount));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor->FilterDescriptors = 0x%p \n",pKSDeviceObject->Descriptor->FilterDescriptors)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor->FilterDescriptors = 0x%p \n",pKSDeviceObject->Descriptor->FilterDescriptors));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor->Version = %lu \n",pKSDeviceObject->Descriptor->Version)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->pDeviceDescriptor->Version = %lu \n",pKSDeviceObject->Descriptor->Version));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->Bag = 0x%p\n",pKSDeviceObject->Bag)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->Bag = 0x%p\n",pKSDeviceObject->Bag));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->Context = 0x%p\n",pKSDeviceObject->Context)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->Context = 0x%p\n",pKSDeviceObject->Context));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->FunctionalDeviceObject = 0x%p\n",pKSDeviceObject->FunctionalDeviceObject)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->FunctionalDeviceObject = 0x%p\n",pKSDeviceObject->FunctionalDeviceObject));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->PhysicalDeviceObject = 0x%p\n",pKSDeviceObject->PhysicalDeviceObject)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->PhysicalDeviceObject = 0x%p\n",pKSDeviceObject->PhysicalDeviceObject));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->NextDeviceObject = 0x%p\n",pKSDeviceObject->NextDeviceObject)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->NextDeviceObject = 0x%p\n",pKSDeviceObject->NextDeviceObject));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->Started = %d\n",pKSDeviceObject->Started)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->Started = %d\n",pKSDeviceObject->Started));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->SystemPowerState = %d\n",pKSDeviceObject->SystemPowerState)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->SystemPowerState = %d\n",pKSDeviceObject->SystemPowerState));
SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->DevicePowerState = %d\n",pKSDeviceObject->DevicePowerState)); SkyWalkerDebugPrint(ENTRY_LEVEL, ("pKsDeviceObject->DevicePowerState = %d\n",pKSDeviceObject->DevicePowerState));
} }

View File

@ -1,414 +1,414 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1TransportPin.cpp File Name : SkyWalker1TransportPin.cpp
Author : Author :
Date : Date :
Purpose : This file contains header for the Transport pin on the Tuner Purpose : This file contains header for the Transport pin on the Tuner
filter. filter.
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1Main.h" //Common For all the Definitions, #include "SkyWalker1Main.h" //Common For all the Definitions,
//Declarations and Library Routines //Declarations and Library Routines
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
VOID PrintBdaTransport(PKS_DATARANGE_BDA_TRANSPORT pBdaTransport); VOID PrintBdaTransport(PKS_DATARANGE_BDA_TRANSPORT pBdaTransport);
VOID PrintBdaTransportInfo(PBDA_TRANSPORT_INFO pBdaTransportInfo); VOID PrintBdaTransportInfo(PBDA_TRANSPORT_INFO pBdaTransportInfo);
VOID PrintKsDataFormat(PKSDATAFORMAT pKsDataFormat); VOID PrintKsDataFormat(PKSDATAFORMAT pKsDataFormat);
PCHAR GetDemodPropertyString(ULONG ulDemodProperty); PCHAR GetDemodPropertyString(ULONG ulDemodProperty);
PCHAR GetExtendedPropertyString(ULONG ulTunerExtendedProperty); PCHAR GetExtendedPropertyString(ULONG ulTunerExtendedProperty);
/* End of Function prototype definitions */ /* End of Function prototype definitions */
/***************************************************************************** /*****************************************************************************
Function : CTransportPin::IntersectDataFormat Function : CTransportPin::IntersectDataFormat
Description : Enables connection of the output pin with a downstream filter. Description : Enables connection of the output pin with a downstream filter.
IN PARAM : IN PARAM :
OUT PARAM : <NTSTATUS> Status of the IntersectDataFormat OUT PARAM : <NTSTATUS> Status of the IntersectDataFormat
PreCondition : None PreCondition : None
PostCondtion : None PostCondtion : None
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : This is called from the PASSIVE_LEVEL_IRQL Note : This is called from the PASSIVE_LEVEL_IRQL
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS CTransportPin::IntersectDataFormat( NTSTATUS CTransportPin::IntersectDataFormat(
IN PVOID pContext, IN PVOID pContext,
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSP_PIN Pin, IN PKSP_PIN Pin,
IN PKSDATARANGE pDataRange, IN PKSDATARANGE pDataRange,
IN PKSDATARANGE pMatchingDataRange, IN PKSDATARANGE pMatchingDataRange,
IN ULONG ulDataBufferSize, IN ULONG ulDataBufferSize,
OUT PVOID pData OPTIONAL, OUT PVOID pData OPTIONAL,
OUT PULONG pulDataSize OUT PULONG pulDataSize
) )
{ {
NTSTATUS ntStatus = STATUS_SUCCESS; NTSTATUS ntStatus = STATUS_SUCCESS;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
if ( ulDataBufferSize < sizeof(KS_DATARANGE_BDA_TRANSPORT) ) if ( ulDataBufferSize < sizeof(KS_DATARANGE_BDA_TRANSPORT) )
{ {
*pulDataSize = sizeof( KS_DATARANGE_BDA_TRANSPORT ); *pulDataSize = sizeof( KS_DATARANGE_BDA_TRANSPORT );
ntStatus = STATUS_BUFFER_OVERFLOW; ntStatus = STATUS_BUFFER_OVERFLOW;
goto ExitDataFormat; goto ExitDataFormat;
} }
else if (pDataRange->FormatSize < sizeof (KS_DATARANGE_BDA_TRANSPORT)) else if (pDataRange->FormatSize < sizeof (KS_DATARANGE_BDA_TRANSPORT))
{ {
ntStatus = STATUS_NO_MATCH; ntStatus = STATUS_NO_MATCH;
goto ExitDataFormat; goto ExitDataFormat;
} }
else else
{ {
*pulDataSize = sizeof( KS_DATARANGE_BDA_TRANSPORT ); *pulDataSize = sizeof( KS_DATARANGE_BDA_TRANSPORT );
RtlCopyMemory( pData, (PVOID)pDataRange, sizeof(KS_DATARANGE_BDA_TRANSPORT)); RtlCopyMemory( pData, (PVOID)pDataRange, sizeof(KS_DATARANGE_BDA_TRANSPORT));
ntStatus = STATUS_SUCCESS; ntStatus = STATUS_SUCCESS;
PrintBdaTransport((PKS_DATARANGE_BDA_TRANSPORT)pDataRange); PrintBdaTransport((PKS_DATARANGE_BDA_TRANSPORT)pDataRange);
} }
ExitDataFormat: ExitDataFormat:
PrintFunctionExit(__FUNCTION__,ntStatus); PrintFunctionExit(__FUNCTION__,ntStatus);
return ntStatus; return ntStatus;
} }
/***************************************************************************** /*****************************************************************************
Function : CTransportPin::SetDigitalDemodProperty Function : CTransportPin::SetDigitalDemodProperty
Description : Sets the value of the digital demodulator node properties. Description : Sets the value of the digital demodulator node properties.
IN PARAM : IN PARAM :
OUT PARAM : <NTSTATUS> Status SUCCESS in case Valid Property Set request OUT PARAM : <NTSTATUS> Status SUCCESS in case Valid Property Set request
STATUS_INVALID_PARAMETER in case of Invalid property set request STATUS_INVALID_PARAMETER in case of Invalid property set request
PreCondition : None PreCondition : None
PostCondtion : Demodulator propery Set in case of successful execution PostCondtion : Demodulator propery Set in case of successful execution
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : This is called from the PASSIVE_LEVEL_IRQL Note : This is called from the PASSIVE_LEVEL_IRQL
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS CTransportPin::SetDigitalDemodProperty( NTSTATUS CTransportPin::SetDigitalDemodProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
) )
{ {
NTSTATUS ntSetStatus = STATUS_SUCCESS; NTSTATUS ntSetStatus = STATUS_SUCCESS;
CTransportPin* pPin; CTransportPin* pPin;
CTunerFilter* pFilter; CTunerFilter* pFilter;
ModulationType NewModulationType; ModulationType NewModulationType;
BinaryConvolutionCodeRate NewFecRate; BinaryConvolutionCodeRate NewFecRate;
ULONG ulNewSymbolRate; ULONG ulNewSymbolRate;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
// Call the BDA support library to // Call the BDA support library to
// validate that the node type is associated with this pin. // validate that the node type is associated with this pin.
// //
ntSetStatus = BdaValidateNodeProperty( pIoRequestPacket, pKSProperty); ntSetStatus = BdaValidateNodeProperty( pIoRequestPacket, pKSProperty);
if (NT_SUCCESS( ntSetStatus)) if (NT_SUCCESS( ntSetStatus))
{ {
// Obtain a pointer to the pin object. // Obtain a pointer to the pin object.
// //
// Because the property dispatch table calls the CTransportPin::SetDigitalDemodProperty() // Because the property dispatch table calls the CTransportPin::SetDigitalDemodProperty()
// method directly, the method must retrieve a pointer to the underlying pin object. // method directly, the method must retrieve a pointer to the underlying pin object.
// //
pPin = reinterpret_cast<CTransportPin *>(KsGetPinFromIrp(pIoRequestPacket)->Context); pPin = reinterpret_cast<CTransportPin *>(KsGetPinFromIrp(pIoRequestPacket)->Context);
// Retrieve the filter context from the pin context. // Retrieve the filter context from the pin context.
// //
pFilter = pPin->GetFilter(); pFilter = pPin->GetFilter();
SkyWalkerDebugPrint(EXTREME_LEVEL,("Set : %s : %lu(%l)",GetDemodPropertyString(pKSProperty->Id),*pulProperty,*((LONG*)(pulProperty)))); SkyWalkerDebugPrint(EXTREME_LEVEL,("Set : %s : %lu(%l)",GetDemodPropertyString(pKSProperty->Id),*pulProperty,*((LONG*)(pulProperty))));
switch (pKSProperty->Id) switch (pKSProperty->Id)
{ {
case KSPROPERTY_BDA_MODULATION_TYPE: case KSPROPERTY_BDA_MODULATION_TYPE:
ntSetStatus = pFilter->SetModulatorType((ModulationType)*pulProperty); ntSetStatus = pFilter->SetModulatorType((ModulationType)*pulProperty);
break; break;
case KSPROPERTY_BDA_INNER_FEC_TYPE: case KSPROPERTY_BDA_INNER_FEC_TYPE:
ntSetStatus = pFilter->SetInnerFecType(*pulProperty); ntSetStatus = pFilter->SetInnerFecType(*pulProperty);
break; break;
case KSPROPERTY_BDA_INNER_FEC_RATE: case KSPROPERTY_BDA_INNER_FEC_RATE:
ntSetStatus = pFilter->SetInnerFecRate((BinaryConvolutionCodeRate)*pulProperty); ntSetStatus = pFilter->SetInnerFecRate((BinaryConvolutionCodeRate)*pulProperty);
break; break;
case KSPROPERTY_BDA_OUTER_FEC_TYPE: case KSPROPERTY_BDA_OUTER_FEC_TYPE:
ntSetStatus = pFilter->SetOuterFecType(*pulProperty); ntSetStatus = pFilter->SetOuterFecType(*pulProperty);
break; break;
case KSPROPERTY_BDA_OUTER_FEC_RATE: case KSPROPERTY_BDA_OUTER_FEC_RATE:
ntSetStatus = pFilter->SetOuterFecRate((BinaryConvolutionCodeRate)*pulProperty); ntSetStatus = pFilter->SetOuterFecRate((BinaryConvolutionCodeRate)*pulProperty);
break; break;
case KSPROPERTY_BDA_SYMBOL_RATE: case KSPROPERTY_BDA_SYMBOL_RATE:
ntSetStatus = pFilter->SetSymbolRate(*pulProperty); ntSetStatus = pFilter->SetSymbolRate(*pulProperty);
break; break;
case KSPROPERTY_BDA_SPECTRAL_INVERSION: case KSPROPERTY_BDA_SPECTRAL_INVERSION:
ntSetStatus = pFilter->SetSpectralInversion((SpectralInversion)*pulProperty); ntSetStatus = pFilter->SetSpectralInversion((SpectralInversion)*pulProperty);
break; break;
case KSPROPERTY_BDA_GUARD_INTERVAL: case KSPROPERTY_BDA_GUARD_INTERVAL:
ntSetStatus = pFilter->SetGuardInterval((GuardInterval)*pulProperty); ntSetStatus = pFilter->SetGuardInterval((GuardInterval)*pulProperty);
break; break;
case KSPROPERTY_BDA_TRANSMISSION_MODE: case KSPROPERTY_BDA_TRANSMISSION_MODE:
ntSetStatus = pFilter->SetTransmissionMode((TransmissionMode)*pulProperty); ntSetStatus = pFilter->SetTransmissionMode((TransmissionMode)*pulProperty);
break; break;
default: default:
ntSetStatus = STATUS_INVALID_PARAMETER; ntSetStatus = STATUS_INVALID_PARAMETER;
break; break;
} }
} }
PrintFunctionExit(__FUNCTION__,ntSetStatus); PrintFunctionExit(__FUNCTION__,ntSetStatus);
return ntSetStatus; return ntSetStatus;
} }
/***************************************************************************** /*****************************************************************************
Function : CTransportPin::GetDigitalDemodProperty Function : CTransportPin::GetDigitalDemodProperty
Description : Gets the value of the digital demodulator node properties. Description : Gets the value of the digital demodulator node properties.
IN PARAM : IN PARAM :
OUT PARAM : <NTSTATUS> Status SUCCESS in case Valid Property Get request OUT PARAM : <NTSTATUS> Status SUCCESS in case Valid Property Get request
STATUS_INVALID_PARAMETER in case of Invalid property Get request STATUS_INVALID_PARAMETER in case of Invalid property Get request
PreCondition : None PreCondition : None
PostCondtion : Demodulator propery returned in case of successful execution PostCondtion : Demodulator propery returned in case of successful execution
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS CTransportPin::GetDigitalDemodProperty( NTSTATUS CTransportPin::GetDigitalDemodProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
) )
{ {
NTSTATUS ntGetStatus = STATUS_SUCCESS; NTSTATUS ntGetStatus = STATUS_SUCCESS;
CTransportPin* pPin; CTransportPin* pPin;
CTunerFilter* pFilter; CTunerFilter* pFilter;
BDATUNER_DEVICE_PARAMETER DemodProperty; BDATUNER_DEVICE_PARAMETER DemodProperty;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
// Call the BDA support library to // Call the BDA support library to
// validate that the node type is associated with this pin. // validate that the node type is associated with this pin.
// //
ntGetStatus = BdaValidateNodeProperty( pIoRequestPacket, pKSProperty); ntGetStatus = BdaValidateNodeProperty( pIoRequestPacket, pKSProperty);
if (NT_SUCCESS( ntGetStatus)) if (NT_SUCCESS( ntGetStatus))
{ {
// Obtain a pointer to the pin object. // Obtain a pointer to the pin object.
// //
// Because the property dispatch table calls the CTransportPin::GetDigitalDemodProperty() // Because the property dispatch table calls the CTransportPin::GetDigitalDemodProperty()
// method directly, the method must retrieve a pointer to the underlying pin object. // method directly, the method must retrieve a pointer to the underlying pin object.
// //
pPin = reinterpret_cast<CTransportPin *>(KsGetPinFromIrp(pIoRequestPacket)->Context); pPin = reinterpret_cast<CTransportPin *>(KsGetPinFromIrp(pIoRequestPacket)->Context);
// Retrieve the filter context from the pin context. // Retrieve the filter context from the pin context.
// //
pFilter = pPin->GetFilter(); pFilter = pPin->GetFilter();
ntGetStatus = pFilter->GetDemodProperty(&DemodProperty); ntGetStatus = pFilter->GetDemodProperty(&DemodProperty);
switch (pKSProperty->Id) switch (pKSProperty->Id)
{ {
case KSPROPERTY_BDA_MODULATION_TYPE: case KSPROPERTY_BDA_MODULATION_TYPE:
*pulProperty = (ModulationType)DemodProperty.CurrentModulationType; *pulProperty = (ModulationType)DemodProperty.CurrentModulationType;
break; break;
case KSPROPERTY_BDA_INNER_FEC_TYPE: case KSPROPERTY_BDA_INNER_FEC_TYPE:
*pulProperty = BDA_FEC_VITERBI; *pulProperty = BDA_FEC_VITERBI;
break; break;
case KSPROPERTY_BDA_INNER_FEC_RATE: case KSPROPERTY_BDA_INNER_FEC_RATE:
*pulProperty = (BinaryConvolutionCodeRate)DemodProperty.InnerFecRate; *pulProperty = (BinaryConvolutionCodeRate)DemodProperty.InnerFecRate;
break; break;
case KSPROPERTY_BDA_OUTER_FEC_TYPE: case KSPROPERTY_BDA_OUTER_FEC_TYPE:
*pulProperty = BDA_FEC_VITERBI; *pulProperty = BDA_FEC_VITERBI;
break; break;
case KSPROPERTY_BDA_OUTER_FEC_RATE: case KSPROPERTY_BDA_OUTER_FEC_RATE:
*pulProperty = (BinaryConvolutionCodeRate)DemodProperty.OuterFecRate; *pulProperty = (BinaryConvolutionCodeRate)DemodProperty.OuterFecRate;
break; break;
case KSPROPERTY_BDA_SYMBOL_RATE: case KSPROPERTY_BDA_SYMBOL_RATE:
*pulProperty = DemodProperty.ulSymbolRate; *pulProperty = DemodProperty.ulSymbolRate;
break; break;
case KSPROPERTY_BDA_SPECTRAL_INVERSION: case KSPROPERTY_BDA_SPECTRAL_INVERSION:
*pulProperty = (SpectralInversion) DemodProperty.CurrentSpectralInversion; *pulProperty = (SpectralInversion) DemodProperty.CurrentSpectralInversion;
break; break;
case KSPROPERTY_BDA_GUARD_INTERVAL: case KSPROPERTY_BDA_GUARD_INTERVAL:
*pulProperty = (GuardInterval) DemodProperty.CurrentGuardInterval; *pulProperty = (GuardInterval) DemodProperty.CurrentGuardInterval;
break; break;
case KSPROPERTY_BDA_TRANSMISSION_MODE: case KSPROPERTY_BDA_TRANSMISSION_MODE:
*pulProperty = (TransmissionMode) DemodProperty.CurrentTransmissionMode; *pulProperty = (TransmissionMode) DemodProperty.CurrentTransmissionMode;
break; break;
default: default:
ntGetStatus = STATUS_INVALID_PARAMETER; ntGetStatus = STATUS_INVALID_PARAMETER;
break; break;
} }
} }
SkyWalkerDebugPrint(EXTREME_LEVEL,("Get : %s : %ul",GetDemodPropertyString(pKSProperty->Id),*pulProperty)); SkyWalkerDebugPrint(EXTREME_LEVEL,("Get : %s : %ul",GetDemodPropertyString(pKSProperty->Id),*pulProperty));
PrintFunctionExit(__FUNCTION__,ntGetStatus); PrintFunctionExit(__FUNCTION__,ntGetStatus);
return ntGetStatus; return ntGetStatus;
} }
/***************************************************************************** /*****************************************************************************
Function : CTransportPin::SetExtendedProperty Function : CTransportPin::SetExtendedProperty
Description : Sets the Extended Property of the Tuner Description : Sets the Extended Property of the Tuner
IN PARAM : IN PIRP pIoRequestPacket, IN PARAM : IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
OUT PARAM : <NTSTATUS> Status SUCCESS in case Valid Property request OUT PARAM : <NTSTATUS> Status SUCCESS in case Valid Property request
STATUS_INVALID_PARAMETER in case of Invalid property request STATUS_INVALID_PARAMETER in case of Invalid property request
Else error from the lower device Else error from the lower device
PreCondition : None PreCondition : None
PostCondtion : Extended Property Set in case of successful execution PostCondtion : Extended Property Set in case of successful execution
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS CTransportPin::SetExtendedProperty( NTSTATUS CTransportPin::SetExtendedProperty(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
IN PULONG pulProperty IN PULONG pulProperty
) )
{ {
NTSTATUS ntSetStatus = STATUS_SUCCESS; NTSTATUS ntSetStatus = STATUS_SUCCESS;
CTransportPin * pPin = NULL; CTransportPin * pPin = NULL;
CTunerFilter* pFilter = NULL; CTunerFilter* pFilter = NULL;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
//Call the BDA support library to //Call the BDA support library to
//validate that the node type is associated with the pin. //validate that the node type is associated with the pin.
//The BdaValidateNodeProperty function validates that a node property //The BdaValidateNodeProperty function validates that a node property
//request is associated with a specific pin. //request is associated with a specific pin.
ntSetStatus = BdaValidateNodeProperty( pIoRequestPacket, pKSProperty); ntSetStatus = BdaValidateNodeProperty( pIoRequestPacket, pKSProperty);
if (NT_SUCCESS( ntSetStatus)) if (NT_SUCCESS( ntSetStatus))
{ {
//Obtain a pointer to the pin object. //Obtain a pointer to the pin object.
//Because the property dispatch table calls the CTransportPin::SetExtendedProperty() //Because the property dispatch table calls the CTransportPin::SetExtendedProperty()
//method directly, the method must retrieve a pointer to the underlying pin object. //method directly, the method must retrieve a pointer to the underlying pin object.
pPin = reinterpret_cast<CTransportPin *>(KsGetPinFromIrp(pIoRequestPacket)->Context); pPin = reinterpret_cast<CTransportPin *>(KsGetPinFromIrp(pIoRequestPacket)->Context);
//Retrieve the filter context from the pin context. //Retrieve the filter context from the pin context.
pFilter = pPin->GetFilter(); pFilter = pPin->GetFilter();
SkyWalkerDebugPrint(EXTREME_LEVEL,("Set : %s : %lu(%l)", SkyWalkerDebugPrint(EXTREME_LEVEL,("Set : %s : %lu(%l)",
GetExtendedPropertyString(pKSProperty->Id), GetExtendedPropertyString(pKSProperty->Id),
*pulProperty, *pulProperty,
*((LONG*)(pulProperty)))); *((LONG*)(pulProperty))));
//Retrieve the actual filter parameter. //Retrieve the actual filter parameter.
switch (pKSProperty->Id) switch (pKSProperty->Id)
{ {
case KSPROPERTY_BDA_DISEQC: case KSPROPERTY_BDA_DISEQC:
ntSetStatus = pFilter->SendDiseqcCommand((PDISEQC_COMMAND) pulProperty); ntSetStatus = pFilter->SendDiseqcCommand((PDISEQC_COMMAND) pulProperty);
break; break;
default: default:
ntSetStatus = STATUS_INVALID_PARAMETER; ntSetStatus = STATUS_INVALID_PARAMETER;
break; break;
} }
} }
PrintFunctionExit(__FUNCTION__,ntSetStatus); PrintFunctionExit(__FUNCTION__,ntSetStatus);
return ntSetStatus; return ntSetStatus;
} }
//Debug Functions //Debug Functions
VOID PrintBdaTransport(PKS_DATARANGE_BDA_TRANSPORT pBdaTransport) VOID PrintBdaTransport(PKS_DATARANGE_BDA_TRANSPORT pBdaTransport)
{ {
PrintBdaTransportInfo(&pBdaTransport->BdaTransportInfo); PrintBdaTransportInfo(&pBdaTransport->BdaTransportInfo);
PrintKsDataFormat(&pBdaTransport->DataRange); PrintKsDataFormat(&pBdaTransport->DataRange);
} }
VOID PrintBdaTransportInfo(PBDA_TRANSPORT_INFO pBdaTransportInfo) VOID PrintBdaTransportInfo(PBDA_TRANSPORT_INFO pBdaTransportInfo)
{ {
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pBdaTransportInfo->ulcbPhyiscalPacket = %lu Bytes\n", SkyWalkerDebugPrint(EXTREME_LEVEL, ("pBdaTransportInfo->ulcbPhyiscalPacket = %lu Bytes\n",
pBdaTransportInfo->ulcbPhyiscalPacket)); pBdaTransportInfo->ulcbPhyiscalPacket));
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pBdaTransportInfo->ulcbPhyiscalFrame = %lu Bytes\n", SkyWalkerDebugPrint(EXTREME_LEVEL, ("pBdaTransportInfo->ulcbPhyiscalFrame = %lu Bytes\n",
pBdaTransportInfo->ulcbPhyiscalFrame)); pBdaTransportInfo->ulcbPhyiscalFrame));
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pBdaTransportInfo->ulcbPhyiscalFrameAlignment = %lu\n", SkyWalkerDebugPrint(EXTREME_LEVEL, ("pBdaTransportInfo->ulcbPhyiscalFrameAlignment = %lu\n",
pBdaTransportInfo->ulcbPhyiscalFrameAlignment)); pBdaTransportInfo->ulcbPhyiscalFrameAlignment));
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pBdaTransportInfo->ulcbPhyiscalPacket = %ll (Normal Active Movie units)\n", SkyWalkerDebugPrint(EXTREME_LEVEL, ("pBdaTransportInfo->ulcbPhyiscalPacket = %ll (Normal Active Movie units)\n",
pBdaTransportInfo->ulcbPhyiscalPacket)); pBdaTransportInfo->ulcbPhyiscalPacket));
} }
VOID PrintKsDataFormat(PKSDATAFORMAT pKsDataFormat) VOID PrintKsDataFormat(PKSDATAFORMAT pKsDataFormat)
{ {
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pKsDataFormat->FormatSize = %lu\n", SkyWalkerDebugPrint(EXTREME_LEVEL, ("pKsDataFormat->FormatSize = %lu\n",
pKsDataFormat->FormatSize)); pKsDataFormat->FormatSize));
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pKsDataFormat->Flags = %lu\n", SkyWalkerDebugPrint(EXTREME_LEVEL, ("pKsDataFormat->Flags = %lu\n",
pKsDataFormat->Flags)); pKsDataFormat->Flags));
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pKsDataFormat->SampleSize = %lu\n", SkyWalkerDebugPrint(EXTREME_LEVEL, ("pKsDataFormat->SampleSize = %lu\n",
pKsDataFormat->SampleSize)); pKsDataFormat->SampleSize));
SkyWalkerDebugPrint(EXTREME_LEVEL, ("pKsDataFormat->Reserved = %lu\n", SkyWalkerDebugPrint(EXTREME_LEVEL, ("pKsDataFormat->Reserved = %lu\n",
pKsDataFormat->Reserved)); pKsDataFormat->Reserved));
} }
PCHAR GetDemodPropertyString(ULONG ulDemodProperty) PCHAR GetDemodPropertyString(ULONG ulDemodProperty)
{ {
switch(ulDemodProperty) switch(ulDemodProperty)
{ {
case KSPROPERTY_BDA_MODULATION_TYPE: case KSPROPERTY_BDA_MODULATION_TYPE:
return "KSPROPERTY_BDA_MODULATION_TYPE"; return "KSPROPERTY_BDA_MODULATION_TYPE";
case KSPROPERTY_BDA_INNER_FEC_TYPE: case KSPROPERTY_BDA_INNER_FEC_TYPE:
return "KSPROPERTY_BDA_INNER_FEC_TYPE"; return "KSPROPERTY_BDA_INNER_FEC_TYPE";
case KSPROPERTY_BDA_INNER_FEC_RATE: case KSPROPERTY_BDA_INNER_FEC_RATE:
return "KSPROPERTY_BDA_INNER_FEC_RATE"; return "KSPROPERTY_BDA_INNER_FEC_RATE";
case KSPROPERTY_BDA_OUTER_FEC_TYPE: case KSPROPERTY_BDA_OUTER_FEC_TYPE:
return "KSPROPERTY_BDA_OUTER_FEC_TYPE"; return "KSPROPERTY_BDA_OUTER_FEC_TYPE";
case KSPROPERTY_BDA_OUTER_FEC_RATE: case KSPROPERTY_BDA_OUTER_FEC_RATE:
return "KSPROPERTY_BDA_OUTER_FEC_RATE"; return "KSPROPERTY_BDA_OUTER_FEC_RATE";
case KSPROPERTY_BDA_SYMBOL_RATE: case KSPROPERTY_BDA_SYMBOL_RATE:
return "KSPROPERTY_BDA_SYMBOL_RATE"; return "KSPROPERTY_BDA_SYMBOL_RATE";
case KSPROPERTY_BDA_SPECTRAL_INVERSION: case KSPROPERTY_BDA_SPECTRAL_INVERSION:
return "KSPROPERTY_BDA_SPECTRAL_INVERSION"; return "KSPROPERTY_BDA_SPECTRAL_INVERSION";
case KSPROPERTY_BDA_GUARD_INTERVAL: case KSPROPERTY_BDA_GUARD_INTERVAL:
return "KSPROPERTY_BDA_GUARD_INTERVAL"; return "KSPROPERTY_BDA_GUARD_INTERVAL";
case KSPROPERTY_BDA_TRANSMISSION_MODE: case KSPROPERTY_BDA_TRANSMISSION_MODE:
return "KSPROPERTY_BDA_TRANSMISSION_MODE"; return "KSPROPERTY_BDA_TRANSMISSION_MODE";
default: default:
return "KSPROPERTY_BDA_INVALID_PROPERTY"; return "KSPROPERTY_BDA_INVALID_PROPERTY";
} }
} }
PCHAR GetExtendedPropertyString(ULONG ulTunerExtendedProperty) PCHAR GetExtendedPropertyString(ULONG ulTunerExtendedProperty)
{ {
switch(ulTunerExtendedProperty) switch(ulTunerExtendedProperty)
{ {
case KSPROPERTY_BDA_DISEQC: case KSPROPERTY_BDA_DISEQC:
return "KSPROPERTY_BDA_DISEQC"; return "KSPROPERTY_BDA_DISEQC";
default: default:
return "KSPROPERTY_BDA_INVALID_PROPERTY"; return "KSPROPERTY_BDA_INVALID_PROPERTY";
} }
} }

View File

@ -1,212 +1,212 @@
/***************************************************************************** /*****************************************************************************
Company : Shree Ganesha Inc. Company : Shree Ganesha Inc.
File Name : SkyWalker1CPin.cpp File Name : SkyWalker1CPin.cpp
Author : Author :
Date : Date :
Purpose : This File Holds the General Pin related declarations Purpose : This File Holds the General Pin related declarations
Revision History: Revision History:
=============================================================================== ===============================================================================
DATE VERSION AUTHOR REMARK DATE VERSION AUTHOR REMARK
=============================================================================== ===============================================================================
XXth April,2009 01 Initial Version XXth April,2009 01 Initial Version
*****************************************************************************/ *****************************************************************************/
/* Include the Library and Other header file */ /* Include the Library and Other header file */
#include "SkyWalker1Main.h" //Common For all the Definitions, #include "SkyWalker1Main.h" //Common For all the Definitions,
//Declarations and Library Routines //Declarations and Library Routines
/* End of Inclusion the Library and Other header file */ /* End of Inclusion the Library and Other header file */
/* Macro Definitions */ /* Macro Definitions */
/* End of Macro Definitions */ /* End of Macro Definitions */
/* Global & Static variables Declaration */ /* Global & Static variables Declaration */
/* End of Global & Static variables Declaration */ /* End of Global & Static variables Declaration */
/* External Variable Declaration */ /* External Variable Declaration */
/* End of External Variable Declaration */ /* End of External Variable Declaration */
/* Declare Enumerations here */ /* Declare Enumerations here */
/* End of Enumeration declaration */ /* End of Enumeration declaration */
/* Function Prototypes */ /* Function Prototypes */
/* End of Function prototype definitions */ /* End of Function prototype definitions */
/***************************************************************************** /*****************************************************************************
Function : CTunerPin::PinCreate Function : CTunerPin::PinCreate
Description : An AVStream minidriver's AVStrMiniPinCreate routine is Description : An AVStream minidriver's AVStrMiniPinCreate routine is
called when a pin is created. Typically, this routine is called when a pin is created. Typically, this routine is
used by minidrivers that want to initialize the context used by minidrivers that want to initialize the context
and resources associated with the pin. and resources associated with the pin.
IN PARAM : <PKSPIN> Pointer to the KSPIN that was just created. IN PARAM : <PKSPIN> Pointer to the KSPIN that was just created.
<PIRP> Pointer to the IRP_MJ_CREATE for Pin <PIRP> Pointer to the IRP_MJ_CREATE for Pin
OUT PARAM : <NTSTATUS> STATUS_SUCCESS in case of successful pin creation OUT PARAM : <NTSTATUS> STATUS_SUCCESS in case of successful pin creation
Failure Code in other cases Failure Code in other cases
PreCondition : None PreCondition : None
PostCondtion : Creates the Tuner pin object and associates it PostCondtion : Creates the Tuner pin object and associates it
with the filter object. with the filter object.
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : None Note : None
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS CTunerPin::PinCreate( IN OUT PKSPIN pKSPin, NTSTATUS CTunerPin::PinCreate( IN OUT PKSPIN pKSPin,
IN PIRP pIoRequestPacket IN PIRP pIoRequestPacket
) )
{ {
NTSTATUS ntCreateStatus = STATUS_SUCCESS; NTSTATUS ntCreateStatus = STATUS_SUCCESS;
CTunerPin* pPin = NULL; //Pointer to the Current Pin Instance CTunerPin* pPin = NULL; //Pointer to the Current Pin Instance
CTunerFilter* pFilter = NULL; //Pointer to the Filter associted with the Pin CTunerFilter* pFilter = NULL; //Pointer to the Filter associted with the Pin
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
SkyWalkerDebugPrint(ENTRY_LEVEL,("Sizeof DISEQC_COMMAND = %d\n",sizeof(DISEQC_COMMAND))); SkyWalkerDebugPrint(ENTRY_LEVEL,("Sizeof DISEQC_COMMAND = %d\n",sizeof(DISEQC_COMMAND)));
//Obtain a pointer to the filter object for which the input pin is created. //Obtain a pointer to the filter object for which the input pin is created.
//The KsGetFilterFromIrp function returns the AVStream filter object //The KsGetFilterFromIrp function returns the AVStream filter object
//associated with a given IRP. //associated with a given IRP.
pFilter = reinterpret_cast<CTunerFilter*>(KsGetFilterFromIrp(pIoRequestPacket)->Context); pFilter = reinterpret_cast<CTunerFilter*>(KsGetFilterFromIrp(pIoRequestPacket)->Context);
//Create the Tuner pin object. //Create the Tuner pin object.
pPin = new(PagedPool,TUNER_MEM_TAG) CTunerPin; // Tags the allocated memory pPin = new(PagedPool,TUNER_MEM_TAG) CTunerPin; // Tags the allocated memory
if (pPin) if (pPin)
{ {
//Link the pin context to the filter context. //Link the pin context to the filter context.
//That is, set the input pin's filter pointer data member to the obtained filter pointer. //That is, set the input pin's filter pointer data member to the obtained filter pointer.
pPin->SetFilter( pFilter); pPin->SetFilter( pFilter);
//Link the pin context to the passed in pointer to the KSPIN structure. //Link the pin context to the passed in pointer to the KSPIN structure.
pKSPin->Context = pPin; pKSPin->Context = pPin;
} }
else else
{ {
ntCreateStatus = STATUS_INSUFFICIENT_RESOURCES; ntCreateStatus = STATUS_INSUFFICIENT_RESOURCES;
} }
PrintFunctionExit(__FUNCTION__,ntCreateStatus); PrintFunctionExit(__FUNCTION__,ntCreateStatus);
return ntCreateStatus; return ntCreateStatus;
} }
/***************************************************************************** /*****************************************************************************
Function : CTunerPin::PinClose Function : CTunerPin::PinClose
Description : An AVStream minidriver's AVStrMiniPinClose routine is Description : An AVStream minidriver's AVStrMiniPinClose routine is
called when a pin is closed.It usually is provided by called when a pin is closed.It usually is provided by
minidrivers that want to free the context and resources minidrivers that want to free the context and resources
associated with the pin. associated with the pin.
IN PARAM : <PKSPIN> Pointer to the KSPIN that was just closed. IN PARAM : <PKSPIN> Pointer to the KSPIN that was just closed.
<PIRP> Pointer to the IRP_MJ_CLOSE for Pin. <PIRP> Pointer to the IRP_MJ_CLOSE for Pin.
OUT PARAM : <NTSTATUS> STATUS_SUCCESS in case of successful pin Close OUT PARAM : <NTSTATUS> STATUS_SUCCESS in case of successful pin Close
Failure Code in other cases Failure Code in other cases
PreCondition : None PreCondition : None
PostCondtion : Deletes the previously created Tuner pin object. PostCondtion : Deletes the previously created Tuner pin object.
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : This is called from the PASSIVE_LEVEL_IRQL Note : This is called from the PASSIVE_LEVEL_IRQL
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS CTunerPin::PinClose( IN OUT PKSPIN pKSPin, NTSTATUS CTunerPin::PinClose( IN OUT PKSPIN pKSPin,
IN PIRP pIoRequestPacket IN PIRP pIoRequestPacket
) )
{ {
NTSTATUS ntCloseStatus = STATUS_SUCCESS; NTSTATUS ntCloseStatus = STATUS_SUCCESS;
CTunerPin* pPin = NULL; //Pointer to the Current Pin Instance CTunerPin* pPin = NULL; //Pointer to the Current Pin Instance
CTunerFilter* pFilter = NULL; //Pointer to the Filter associted with the Pin CTunerFilter* pFilter = NULL; //Pointer to the Filter associted with the Pin
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
// Retrieve the Tuner pin object from the passed in // Retrieve the Tuner pin object from the passed in
// KSPIN structure's context member. // KSPIN structure's context member.
// //
pPin = reinterpret_cast<CTunerPin*>(pKSPin->Context); pPin = reinterpret_cast<CTunerPin*>(pKSPin->Context);
if(IS_VALID(pPin)) if(IS_VALID(pPin))
{ {
delete pPin; delete pPin;
pPin = NULL; pPin = NULL;
} }
PrintFunctionExit(__FUNCTION__,ntCloseStatus); PrintFunctionExit(__FUNCTION__,ntCloseStatus);
return ntCloseStatus; return ntCloseStatus;
} }
/***************************************************************************** /*****************************************************************************
Function : CTunerPin::GetSignalStatus Function : CTunerPin::GetSignalStatus
Description : Retrieves the value of the signal statistics properties. Description : Retrieves the value of the signal statistics properties.
IN PARAM : IN PIRP pIoRequestPacket, IN PARAM : IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
OUT PULONG pulProperty OUT PULONG pulProperty
OUT PARAM : <NTSTATUS> Status SUCCESS in case Valid Property request OUT PARAM : <NTSTATUS> Status SUCCESS in case Valid Property request
STATUS_INVALID_PARAMETER in case of Invalid property request STATUS_INVALID_PARAMETER in case of Invalid property request
Else error from the lower device Else error from the lower device
PreCondition : None PreCondition : None
PostCondtion : Signal Status read in case of successful execution PostCondtion : Signal Status read in case of successful execution
Logic : NONE Logic : NONE
Assumption : NONE Assumption : NONE
Note : NONE Note : NONE
Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER > Revision History: <REVISION HISTORY OF THE FUNCTION, MUST BE MAINTAINED BY MAINTAINER >
*****************************************************************************/ *****************************************************************************/
NTSTATUS CTunerPin::GetSignalStatus( NTSTATUS CTunerPin::GetSignalStatus(
IN PIRP pIoRequestPacket, IN PIRP pIoRequestPacket,
IN PKSPROPERTY pKSProperty, IN PKSPROPERTY pKSProperty,
OUT PULONG pulProperty OUT PULONG pulProperty
) )
{ {
NTSTATUS ntGetStatus = STATUS_SUCCESS; NTSTATUS ntGetStatus = STATUS_SUCCESS;
CTunerPin* pPin = NULL; //Pointer to the Current Pin Instance CTunerPin* pPin = NULL; //Pointer to the Current Pin Instance
CTunerFilter* pFilter = NULL; //Pointer to the Filter associted with the Pin CTunerFilter* pFilter = NULL; //Pointer to the Filter associted with the Pin
BDATUNER_DEVICE_STATUS TunerStatus; BDATUNER_DEVICE_STATUS TunerStatus;
PrintFunctionEntry(__FUNCTION__); PrintFunctionEntry(__FUNCTION__);
// Call the BDA support library to // Call the BDA support library to
// validate that the node type is associated with this pin. // validate that the node type is associated with this pin.
ntGetStatus = BdaValidateNodeProperty( pIoRequestPacket, pKSProperty); ntGetStatus = BdaValidateNodeProperty( pIoRequestPacket, pKSProperty);
if (NT_SUCCESS( ntGetStatus)) if (NT_SUCCESS( ntGetStatus))
{ {
// Obtain a pointer to the pin object. // Obtain a pointer to the pin object.
// //
// Because the property dispatch table calls the CTunerPin::GetSignalStatus() // Because the property dispatch table calls the CTunerPin::GetSignalStatus()
// method directly, the method must retrieve a pointer to the underlying pin object. // method directly, the method must retrieve a pointer to the underlying pin object.
// //
pPin = reinterpret_cast<CTunerPin *>(KsGetPinFromIrp(pIoRequestPacket)->Context); pPin = reinterpret_cast<CTunerPin *>(KsGetPinFromIrp(pIoRequestPacket)->Context);
// Retrieve the filter context from the pin context. // Retrieve the filter context from the pin context.
// //
pFilter = pPin->GetFilter(); pFilter = pPin->GetFilter();
ntGetStatus = pFilter->GetStatus( &TunerStatus); ntGetStatus = pFilter->GetStatus( &TunerStatus);
if (ntGetStatus == STATUS_SUCCESS) if (ntGetStatus == STATUS_SUCCESS)
{ {
switch (pKSProperty->Id) switch (pKSProperty->Id)
{ {
case KSPROPERTY_BDA_SIGNAL_LOCKED: case KSPROPERTY_BDA_SIGNAL_LOCKED:
*pulProperty = TunerStatus.fSignalLocked; *pulProperty = TunerStatus.fSignalLocked;
SkyWalkerDebugPrint(EXTREME_LEVEL,("Signal Lock = 0x%02X\n",*pulProperty)); SkyWalkerDebugPrint(EXTREME_LEVEL,("Signal Lock = 0x%02X\n",*pulProperty));
break; break;
case KSPROPERTY_BDA_SIGNAL_QUALITY: case KSPROPERTY_BDA_SIGNAL_QUALITY:
*pulProperty = TunerStatus.dwSignalQuality; *pulProperty = TunerStatus.dwSignalQuality;
SkyWalkerDebugPrint(EXTREME_LEVEL,("Signal Quality = %lu\n",*pulProperty)); SkyWalkerDebugPrint(EXTREME_LEVEL,("Signal Quality = %lu\n",*pulProperty));
break; break;
case KSPROPERTY_BDA_SIGNAL_PRESENT: case KSPROPERTY_BDA_SIGNAL_PRESENT:
*pulProperty = TunerStatus.fCarrierPresent; *pulProperty = TunerStatus.fCarrierPresent;
SkyWalkerDebugPrint(EXTREME_LEVEL,("Signal Present = 0x%02X\n",*pulProperty)); SkyWalkerDebugPrint(EXTREME_LEVEL,("Signal Present = 0x%02X\n",*pulProperty));
break; break;
case KSPROPERTY_BDA_SIGNAL_STRENGTH: case KSPROPERTY_BDA_SIGNAL_STRENGTH:
*pulProperty = TunerStatus.dwSignalStrength; *pulProperty = TunerStatus.dwSignalStrength;
SkyWalkerDebugPrint(EXTREME_LEVEL,("Signal Strength = %lu\n", *pulProperty)); SkyWalkerDebugPrint(EXTREME_LEVEL,("Signal Strength = %lu\n", *pulProperty));
break; break;
default: default:
ntGetStatus = STATUS_INVALID_PARAMETER; ntGetStatus = STATUS_INVALID_PARAMETER;
} }
} }
} }
PrintFunctionExit(__FUNCTION__,ntGetStatus); PrintFunctionExit(__FUNCTION__,ntGetStatus);
return ntGetStatus; return ntGetStatus;
} }

View File

@ -1,142 +1,142 @@
; SkyWalker2Installer.INF -- This file installs SkyWalker2 Driver ; SkyWalker2Installer.INF -- This file installs SkyWalker2 Driver
; ;
[Version] [Version]
signature="$CHICAGO$" signature="$CHICAGO$"
Class=Media Class=Media
ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318} ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
Provider=%SGI% Provider=%SGI%
CatalogFile=SkyWalker2Installer.cat CatalogFile=SkyWalker2Installer.cat
DriverVer= 8/17/2009 DriverVer= 8/17/2009
; F i l e c o p y i n g s e c t i o n s (where the files go to). ; F i l e c o p y i n g s e c t i o n s (where the files go to).
; ;
[DestinationDirs] [DestinationDirs]
DefaultDestDir=10,system32\drivers DefaultDestDir=10,system32\drivers
[Manufacturer] [Manufacturer]
%SGI%=SGI %SGI%=SGI
[ControlFlags] [ControlFlags]
;ExcludeFromSelect=* ;ExcludeFromSelect=*
;ExcludeFromSelect.NT=* ;ExcludeFromSelect.NT=*
; =================== Generic ================================== ; =================== Generic ==================================
[SGI] [SGI]
%SkyWalker2.DeviceDesc%=SkyWalker2.Device,USB\VID_09C0&PID_0206 ;SkyWalker2 %SkyWalker2.DeviceDesc%=SkyWalker2.Device,USB\VID_09C0&PID_0206 ;SkyWalker2
[SkyWalker2.Device] [SkyWalker2.Device]
Include = ks.inf, kscaptur.inf, bda.inf Include = ks.inf, kscaptur.inf, bda.inf
needs = KS.Registration, KSCAPTUR.Registration, BDA.Installation needs = KS.Registration, KSCAPTUR.Registration, BDA.Installation
AddReg = SkyWalker2.AddReg AddReg = SkyWalker2.AddReg
CopyFiles = SkyWalker2.CopyDrivers CopyFiles = SkyWalker2.CopyDrivers
[SkyWalker2.Device.NT] [SkyWalker2.Device.NT]
Include = ks.inf, kscaptur.inf, bda.inf Include = ks.inf, kscaptur.inf, bda.inf
needs = KS.Registration.NT, KSCAPTUR.Registration.NT, BDA.Installation.NT needs = KS.Registration.NT, KSCAPTUR.Registration.NT, BDA.Installation.NT
;AddReg = SkyWalker2.AddReg ;AddReg = SkyWalker2.AddReg
CopyFiles = SkyWalker2.CopyDrivers CopyFiles = SkyWalker2.CopyDrivers
; KnownFiles = SkyWalker2.KnownFiles ; KnownFiles = SkyWalker2.KnownFiles
[SkyWalker2.Device.NT.Services] [SkyWalker2.Device.NT.Services]
Addservice=SkyWalker2TVTuner, 0x00000002, SkyWalker2.AddService Addservice=SkyWalker2TVTuner, 0x00000002, SkyWalker2.AddService
[SkyWalker2.AddService] [SkyWalker2.AddService]
DisplayName=%SkyWalker2.FriendlyName% DisplayName=%SkyWalker2.FriendlyName%
ServiceType=1 ; SERVICE_KERNEL_DRIVER ServiceType=1 ; SERVICE_KERNEL_DRIVER
StartType=3 ; SERVICE_DEMAND_START StartType=3 ; SERVICE_DEMAND_START
ErrorControl=1 ; SERVICE_ERROR_NORMAL ErrorControl=1 ; SERVICE_ERROR_NORMAL
ServiceBinary=%10%\System32\Drivers\SkyWalker1TVTuner.sys ServiceBinary=%10%\System32\Drivers\SkyWalker1TVTuner.sys
LoadOrderGroup=ExtendedBase LoadOrderGroup=ExtendedBase
[SkyWalker2.CopyDrivers] [SkyWalker2.CopyDrivers]
SkyWalker1TVTuner.sys SkyWalker1TVTuner.sys
[SkyWalker2.AddReg] [SkyWalker2.AddReg]
HKR,,DevLoader,,*NTKERN HKR,,DevLoader,,*NTKERN
HKR,,NTMPDriver,,SkyWalker1TVTuner.sys HKR,,NTMPDriver,,SkyWalker1TVTuner.sys
HKR,,PageOutWhenUnopened,3,01 HKR,,PageOutWhenUnopened,3,01
[SkyWalker2.Device.Interfaces] [SkyWalker2.Device.Interfaces]
AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,SkyWalker2.Receiver.Interfaces AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,SkyWalker2.Receiver.Interfaces
AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,SkyWalker2.Tuner.Interfaces AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,SkyWalker2.Tuner.Interfaces
[SkyWalker2.Device.NT.Interfaces] [SkyWalker2.Device.NT.Interfaces]
AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,SkyWalker2.Receiver.Interfaces AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,SkyWalker2.Receiver.Interfaces
AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,SkyWalker2.Tuner.Interfaces AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,SkyWalker2.Tuner.Interfaces
[SkyWalker2.Tuner.Interfaces] [SkyWalker2.Tuner.Interfaces]
AddReg=SkyWalker2.Tuner.Interfaces.AddReg AddReg=SkyWalker2.Tuner.Interfaces.AddReg
[SkyWalker2.Tuner.Interfaces.AddReg] [SkyWalker2.Tuner.Interfaces.AddReg]
HKR,,CLSID,,%KSProxy.CLSID% HKR,,CLSID,,%KSProxy.CLSID%
HKR,,FriendlyName,,%SkyWalker2.Tuner.FriendlyName% HKR,,FriendlyName,,%SkyWalker2.Tuner.FriendlyName%
[SkyWalker2.Receiver.Interfaces] [SkyWalker2.Receiver.Interfaces]
AddReg=SkyWalker2.Receiver.Interfaces.AddReg AddReg=SkyWalker2.Receiver.Interfaces.AddReg
[SkyWalker2.Receiver.Interfaces.AddReg] [SkyWalker2.Receiver.Interfaces.AddReg]
HKR,,CLSID,,%KSProxy.CLSID% HKR,,CLSID,,%KSProxy.CLSID%
HKR,,FriendlyName,,%SkyWalker2.Receiver.FriendlyName% HKR,,FriendlyName,,%SkyWalker2.Receiver.FriendlyName%
[Strings] [Strings]
;non-localizable ;non-localizable
SGI="Plethorasoft" SGI="Plethorasoft"
MfgName="SGI" MfgName="SGI"
SkyWalker2.DeviceDesc="SkyWalker2 BDA TVTuner" SkyWalker2.DeviceDesc="SkyWalker2 BDA TVTuner"
SkyWalker2.Tuner.FriendlyName="SkyWalker2 TV Tuner" SkyWalker2.Tuner.FriendlyName="SkyWalker2 TV Tuner"
SkyWalker2.Receiver.FriendlyName="SkyWalker2 TV Receiver" SkyWalker2.Receiver.FriendlyName="SkyWalker2 TV Receiver"
SkyWalker2.Tuner="SkyWalker2.Tuner" SkyWalker2.Tuner="SkyWalker2.Tuner"
KSProxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}" KSProxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
KSCATEGORY_BDA_NETWORK_TUNER="{71985F48-1CA1-11d3-9CC8-00C04F7971E0}" KSCATEGORY_BDA_NETWORK_TUNER="{71985F48-1CA1-11d3-9CC8-00C04F7971E0}"
KSCATEGORY_BDA_RECEIVER_COMPONENT="{FD0A5AF4-B41D-11d2-9C95-00C04F7971E0}" KSCATEGORY_BDA_RECEIVER_COMPONENT="{FD0A5AF4-B41D-11d2-9C95-00C04F7971E0}"
SKYWALKER_TUNER="{5C4E764F-AB43-46A9-B21E-8529C70F0A23}" SKYWALKER_TUNER="{5C4E764F-AB43-46A9-B21E-8529C70F0A23}"
SKYWALKER_CAPTURE="{0F8F74D9-E524-4D05-BB60-F0C69ACB1756}" SKYWALKER_CAPTURE="{0F8F74D9-E524-4D05-BB60-F0C69ACB1756}"
; ;
; ServiceType values ; ServiceType values
SERVICE_KERNEL_DRIVER = 0x00000001 SERVICE_KERNEL_DRIVER = 0x00000001
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002 SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
SERVICE_ADAPTER = 0x00000004 SERVICE_ADAPTER = 0x00000004
SERVICE_RECOGNIZER_DRIVER = 0x00000008 SERVICE_RECOGNIZER_DRIVER = 0x00000008
SERVICE_WIN32_OWN_PROCESS = 0x00000010 SERVICE_WIN32_OWN_PROCESS = 0x00000010
SERVICE_WIN32_SHARE_PROCESS = 0x00000020 SERVICE_WIN32_SHARE_PROCESS = 0x00000020
SERVICE_INTERACTIVE_PROCESS = 0x00000100 SERVICE_INTERACTIVE_PROCESS = 0x00000100
SERVICE_INTERACTIVE_SHARE_PROCESS = 0x00000120 SERVICE_INTERACTIVE_SHARE_PROCESS = 0x00000120
; StartType values ; StartType values
SERVICE_BOOT_START = 0x00000000 SERVICE_BOOT_START = 0x00000000
SERVICE_SYSTEM_START = 0x00000001 SERVICE_SYSTEM_START = 0x00000001
SERVICE_AUTO_START = 0x00000002 SERVICE_AUTO_START = 0x00000002
SERVICE_DEMAND_START = 0x00000003 SERVICE_DEMAND_START = 0x00000003
SERVICE_DISABLED = 0x00000004 SERVICE_DISABLED = 0x00000004
; ErrorControl values ; ErrorControl values
SERVICE_ERROR_IGNORE = 0x00000000 SERVICE_ERROR_IGNORE = 0x00000000
SERVICE_ERROR_NORMAL = 0x00000001 SERVICE_ERROR_NORMAL = 0x00000001
SERVICE_ERROR_SEVERE = 0x00000002 SERVICE_ERROR_SEVERE = 0x00000002
SERVICE_ERROR_CRITICAL = 0x00000003 SERVICE_ERROR_CRITICAL = 0x00000003
; Characteristic flags ; Characteristic flags
NCF_VIRTUAL = 0x0001 NCF_VIRTUAL = 0x0001
NCF_WRAPPER = 0x0002 NCF_WRAPPER = 0x0002
NCF_PHYSICAL = 0x0004 NCF_PHYSICAL = 0x0004
NCF_HIDDEN = 0x0008 NCF_HIDDEN = 0x0008
NCF_NO_SERVICE = 0x0010 NCF_NO_SERVICE = 0x0010
NCF_NOT_USER_REMOVABLE = 0x0020 NCF_NOT_USER_REMOVABLE = 0x0020
NCF_HAS_UI = 0x0080 NCF_HAS_UI = 0x0080
NCF_MODEM = 0x0100 NCF_MODEM = 0x0100
; Registry types ; Registry types
REG_MULTI_SZ = 0x10000 REG_MULTI_SZ = 0x10000
REG_EXPAND_SZ = 0x20000 REG_EXPAND_SZ = 0x20000
REG_DWORD = 0x10001 REG_DWORD = 0x10001
; Win9x Compatible Types ; Win9x Compatible Types
REG_BINARY = 17 REG_BINARY = 17
REG_SZ = 0 REG_SZ = 0
; Service install flags ; Service install flags
SPSVCINST_TAGTOFRONT = 0x1 SPSVCINST_TAGTOFRONT = 0x1
SPSVCINST_ASSOCSERVICE = 0x2 SPSVCINST_ASSOCSERVICE = 0x2

View File

@ -1,62 +1,62 @@
############################################################################# #############################################################################
# Shree Ganesha Inc. # Shree Ganesha Inc.
# Sources File for the Skywalker1 TV Tuner # Sources File for the Skywalker1 TV Tuner
# Date : 29th September, 2009 # Date : 29th September, 2009
# Description : This file is a must for the Compilation of the # Description : This file is a must for the Compilation of the
# Skywalker Driver. # Skywalker Driver.
# #
########################################################################## ##########################################################################
TARGETNAME=SkyWalker1TVTuner # Set driver's name TARGETNAME=SkyWalker1TVTuner # Set driver's name
TARGETTYPE=DRIVER # Set type of file built, for example, program, DLL, or driver TARGETTYPE=DRIVER # Set type of file built, for example, program, DLL, or driver
# For BDA minidriver, set to DRIVER. # For BDA minidriver, set to DRIVER.
TARGETPATH=obj$(BUILD_ALT_DIR) # Set destination directory for the built file TARGETPATH=obj$(BUILD_ALT_DIR) # Set destination directory for the built file
# Depending on whether your build environment is "free" or "checked", # Depending on whether your build environment is "free" or "checked",
# the BUILD_ALT_DIR variable appends "fre" or "chk" to the \obj subdirectory. # the BUILD_ALT_DIR variable appends "fre" or "chk" to the \obj subdirectory.
DRIVERTYPE=WDM # Set type of driver, can be set to either WDM or VXD. DRIVERTYPE=WDM # Set type of driver, can be set to either WDM or VXD.
# For BDA, set to WDM. # For BDA, set to WDM.
# Generate .SYM and .PDB (map) files. These files map names to addresses. # Generate .SYM and .PDB (map) files. These files map names to addresses.
# Required to debug on Win9x. # Required to debug on Win9x.
USE_MAPSYM=1 USE_MAPSYM=1
# Point to the header files that the sample source requires. # Point to the header files that the sample source requires.
INCLUDES= \ INCLUDES= \
$(DDK_INC_PATH); \ $(DDK_INC_PATH); \
$(DDK_INC_PATH)\wdm; \ $(DDK_INC_PATH)\wdm; \
$(SDK_INC_PATH); \ $(SDK_INC_PATH); \
$(SDK_PATH)\AMovie\Inc; \ $(SDK_PATH)\AMovie\Inc; \
$(INCLUDES) $(INCLUDES)
# Point to the library files that the sample source requires. # Point to the library files that the sample source requires.
TARGETLIBS= \ TARGETLIBS= \
$(DDK_LIB_PATH)\ks.lib \ $(DDK_LIB_PATH)\ks.lib \
$(DDK_LIB_PATH)\ksguid.lib \ $(DDK_LIB_PATH)\ksguid.lib \
$(DDK_LIB_PATH)\BdaSup.lib \ $(DDK_LIB_PATH)\BdaSup.lib \
$(DDK_LIB_PATH)\usbd.lib $(DDK_LIB_PATH)\usbd.lib
# The following macros are used with the Soft-ICE debugging tool. # The following macros are used with the Soft-ICE debugging tool.
!ifdef BUILD_SOFTICE_SYMBOLS !ifdef BUILD_SOFTICE_SYMBOLS
TARGETPATHEX=$(TARGETPATH)\$(TARGET_DIRECTORY) TARGETPATHEX=$(TARGETPATH)\$(TARGET_DIRECTORY)
NTTARGETFILES=$(TARGETPATH)\$(TARGETNAME).dbg NTTARGETFILES=$(TARGETPATH)\$(TARGETNAME).dbg
NTTARGETFILES=$(TARGETPATHEX)\$(TARGETNAME).nms $(NTTARGETFILES) NTTARGETFILES=$(TARGETPATHEX)\$(TARGETNAME).nms $(NTTARGETFILES)
!endif !endif
# Source files that must be compiled. # Source files that must be compiled.
SOURCES = SkyWalker1TunerPin.cpp \ SOURCES = SkyWalker1TunerPin.cpp \
SkyWalker1AntennaPin.cpp \ SkyWalker1AntennaPin.cpp \
SkyWalker1CaptureFilter.cpp \ SkyWalker1CaptureFilter.cpp \
SkyWalker1CaptureFilterDefinitions.cpp \ SkyWalker1CaptureFilterDefinitions.cpp \
SkyWalker1CapturePin.cpp \ SkyWalker1CapturePin.cpp \
SkyWalker1Control.cpp \ SkyWalker1Control.cpp \
SkyWalker1Device.cpp \ SkyWalker1Device.cpp \
SkyWalker1Main.cpp \ SkyWalker1Main.cpp \
SkyWalker1PnP.cpp \ SkyWalker1PnP.cpp \
SkyWalker1TransportPin.cpp \ SkyWalker1TransportPin.cpp \
SkyWalker1TunerFilter.cpp \ SkyWalker1TunerFilter.cpp \
SkyWalker1TunerFilterDefinitions.cpp \ SkyWalker1TunerFilterDefinitions.cpp \
SkyWalker1USB.cpp \ SkyWalker1USB.cpp \
SkyWalker1Utility.cpp SkyWalker1Utility.cpp

View File

@ -1,142 +1,142 @@
; SkyWalker1Installer.INF -- This file installs SkyWalker1 Driver ; SkyWalker1Installer.INF -- This file installs SkyWalker1 Driver
; ;
[Version] [Version]
signature="$CHICAGO$" signature="$CHICAGO$"
Class=Media Class=Media
ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318} ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
Provider=%SGI% Provider=%SGI%
CatalogFile=SkyWalker1Installer.cat CatalogFile=SkyWalker1Installer.cat
DriverVer= 8/17/2009 DriverVer= 8/17/2009
; F i l e c o p y i n g s e c t i o n s (where the files go to). ; F i l e c o p y i n g s e c t i o n s (where the files go to).
; ;
[DestinationDirs] [DestinationDirs]
DefaultDestDir=10,system32\drivers DefaultDestDir=10,system32\drivers
[Manufacturer] [Manufacturer]
%SGI%=SGI %SGI%=SGI
[ControlFlags] [ControlFlags]
;ExcludeFromSelect=* ;ExcludeFromSelect=*
;ExcludeFromSelect.NT=* ;ExcludeFromSelect.NT=*
; =================== Generic ================================== ; =================== Generic ==================================
[SGI] [SGI]
%SkyWalker1.DeviceDesc%=Skywalker1.Device,USB\VID_09C0&PID_0203 ;SkyWalker1 %SkyWalker1.DeviceDesc%=Skywalker1.Device,USB\VID_09C0&PID_0203 ;SkyWalker1
[Skywalker1.Device] [Skywalker1.Device]
Include = ks.inf, kscaptur.inf, bda.inf Include = ks.inf, kscaptur.inf, bda.inf
needs = KS.Registration, KSCAPTUR.Registration, BDA.Installation needs = KS.Registration, KSCAPTUR.Registration, BDA.Installation
AddReg = Skywalker1.AddReg AddReg = Skywalker1.AddReg
CopyFiles = Skywalker1.CopyDrivers CopyFiles = Skywalker1.CopyDrivers
[Skywalker1.Device.NT] [Skywalker1.Device.NT]
Include = ks.inf, kscaptur.inf, bda.inf Include = ks.inf, kscaptur.inf, bda.inf
needs = KS.Registration.NT, KSCAPTUR.Registration.NT, BDA.Installation.NT needs = KS.Registration.NT, KSCAPTUR.Registration.NT, BDA.Installation.NT
;AddReg = Skywalker1.AddReg ;AddReg = Skywalker1.AddReg
CopyFiles = Skywalker1.CopyDrivers CopyFiles = Skywalker1.CopyDrivers
; KnownFiles = Skywalker1.KnownFiles ; KnownFiles = Skywalker1.KnownFiles
[Skywalker1.Device.NT.Services] [Skywalker1.Device.NT.Services]
Addservice=SkyWalker1TVTuner, 0x00000002, Skywalker1.AddService Addservice=SkyWalker1TVTuner, 0x00000002, Skywalker1.AddService
[Skywalker1.AddService] [Skywalker1.AddService]
DisplayName=%SkyWalker1.FriendlyName% DisplayName=%SkyWalker1.FriendlyName%
ServiceType=1 ; SERVICE_KERNEL_DRIVER ServiceType=1 ; SERVICE_KERNEL_DRIVER
StartType=3 ; SERVICE_DEMAND_START StartType=3 ; SERVICE_DEMAND_START
ErrorControl=1 ; SERVICE_ERROR_NORMAL ErrorControl=1 ; SERVICE_ERROR_NORMAL
ServiceBinary=%10%\System32\Drivers\SkyWalker1TVTuner.sys ServiceBinary=%10%\System32\Drivers\SkyWalker1TVTuner.sys
LoadOrderGroup=ExtendedBase LoadOrderGroup=ExtendedBase
[Skywalker1.CopyDrivers] [Skywalker1.CopyDrivers]
SkyWalker1TVTuner.sys SkyWalker1TVTuner.sys
[Skywalker1.AddReg] [Skywalker1.AddReg]
HKR,,DevLoader,,*NTKERN HKR,,DevLoader,,*NTKERN
HKR,,NTMPDriver,,SkyWalker1TVTuner.sys HKR,,NTMPDriver,,SkyWalker1TVTuner.sys
HKR,,PageOutWhenUnopened,3,01 HKR,,PageOutWhenUnopened,3,01
[Skywalker1.Device.Interfaces] [Skywalker1.Device.Interfaces]
AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,Skywalker1.Receiver.Interfaces AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,Skywalker1.Receiver.Interfaces
AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,Skywalker1.Tuner.Interfaces AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,Skywalker1.Tuner.Interfaces
[Skywalker1.Device.NT.Interfaces] [Skywalker1.Device.NT.Interfaces]
AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,Skywalker1.Receiver.Interfaces AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,Skywalker1.Receiver.Interfaces
AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,Skywalker1.Tuner.Interfaces AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,Skywalker1.Tuner.Interfaces
[Skywalker1.Tuner.Interfaces] [Skywalker1.Tuner.Interfaces]
AddReg=Skywalker1.Tuner.Interfaces.AddReg AddReg=Skywalker1.Tuner.Interfaces.AddReg
[Skywalker1.Tuner.Interfaces.AddReg] [Skywalker1.Tuner.Interfaces.AddReg]
HKR,,CLSID,,%KSProxy.CLSID% HKR,,CLSID,,%KSProxy.CLSID%
HKR,,FriendlyName,,%SkyWalker1.Tuner.FriendlyName% HKR,,FriendlyName,,%SkyWalker1.Tuner.FriendlyName%
[Skywalker1.Receiver.Interfaces] [Skywalker1.Receiver.Interfaces]
AddReg=Skywalker1.Receiver.Interfaces.AddReg AddReg=Skywalker1.Receiver.Interfaces.AddReg
[Skywalker1.Receiver.Interfaces.AddReg] [Skywalker1.Receiver.Interfaces.AddReg]
HKR,,CLSID,,%KSProxy.CLSID% HKR,,CLSID,,%KSProxy.CLSID%
HKR,,FriendlyName,,%SkyWalker1.Receiver.FriendlyName% HKR,,FriendlyName,,%SkyWalker1.Receiver.FriendlyName%
[Strings] [Strings]
;non-localizable ;non-localizable
SGI="Plethorasoft" SGI="Plethorasoft"
MfgName="SGI" MfgName="SGI"
SkyWalker1.DeviceDesc="SkyWalker1 BDA TVTuner" SkyWalker1.DeviceDesc="SkyWalker1 BDA TVTuner"
SkyWalker1.Tuner.FriendlyName="SkyWalker1 TV Tuner" SkyWalker1.Tuner.FriendlyName="SkyWalker1 TV Tuner"
SkyWalker1.Receiver.FriendlyName="SkyWalker1 TV Receiver" SkyWalker1.Receiver.FriendlyName="SkyWalker1 TV Receiver"
SkyWalker1.Tuner="SkyWalker1.Tuner" SkyWalker1.Tuner="SkyWalker1.Tuner"
KSProxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}" KSProxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
KSCATEGORY_BDA_NETWORK_TUNER="{71985F48-1CA1-11d3-9CC8-00C04F7971E0}" KSCATEGORY_BDA_NETWORK_TUNER="{71985F48-1CA1-11d3-9CC8-00C04F7971E0}"
KSCATEGORY_BDA_RECEIVER_COMPONENT="{FD0A5AF4-B41D-11d2-9C95-00C04F7971E0}" KSCATEGORY_BDA_RECEIVER_COMPONENT="{FD0A5AF4-B41D-11d2-9C95-00C04F7971E0}"
SKYWALKER_TUNER="{5C4E764F-AB43-46A9-B21E-8529C70F0A23}" SKYWALKER_TUNER="{5C4E764F-AB43-46A9-B21E-8529C70F0A23}"
SKYWALKER_CAPTURE="{0F8F74D9-E524-4D05-BB60-F0C69ACB1756}" SKYWALKER_CAPTURE="{0F8F74D9-E524-4D05-BB60-F0C69ACB1756}"
; ;
; ServiceType values ; ServiceType values
SERVICE_KERNEL_DRIVER = 0x00000001 SERVICE_KERNEL_DRIVER = 0x00000001
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002 SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
SERVICE_ADAPTER = 0x00000004 SERVICE_ADAPTER = 0x00000004
SERVICE_RECOGNIZER_DRIVER = 0x00000008 SERVICE_RECOGNIZER_DRIVER = 0x00000008
SERVICE_WIN32_OWN_PROCESS = 0x00000010 SERVICE_WIN32_OWN_PROCESS = 0x00000010
SERVICE_WIN32_SHARE_PROCESS = 0x00000020 SERVICE_WIN32_SHARE_PROCESS = 0x00000020
SERVICE_INTERACTIVE_PROCESS = 0x00000100 SERVICE_INTERACTIVE_PROCESS = 0x00000100
SERVICE_INTERACTIVE_SHARE_PROCESS = 0x00000120 SERVICE_INTERACTIVE_SHARE_PROCESS = 0x00000120
; StartType values ; StartType values
SERVICE_BOOT_START = 0x00000000 SERVICE_BOOT_START = 0x00000000
SERVICE_SYSTEM_START = 0x00000001 SERVICE_SYSTEM_START = 0x00000001
SERVICE_AUTO_START = 0x00000002 SERVICE_AUTO_START = 0x00000002
SERVICE_DEMAND_START = 0x00000003 SERVICE_DEMAND_START = 0x00000003
SERVICE_DISABLED = 0x00000004 SERVICE_DISABLED = 0x00000004
; ErrorControl values ; ErrorControl values
SERVICE_ERROR_IGNORE = 0x00000000 SERVICE_ERROR_IGNORE = 0x00000000
SERVICE_ERROR_NORMAL = 0x00000001 SERVICE_ERROR_NORMAL = 0x00000001
SERVICE_ERROR_SEVERE = 0x00000002 SERVICE_ERROR_SEVERE = 0x00000002
SERVICE_ERROR_CRITICAL = 0x00000003 SERVICE_ERROR_CRITICAL = 0x00000003
; Characteristic flags ; Characteristic flags
NCF_VIRTUAL = 0x0001 NCF_VIRTUAL = 0x0001
NCF_WRAPPER = 0x0002 NCF_WRAPPER = 0x0002
NCF_PHYSICAL = 0x0004 NCF_PHYSICAL = 0x0004
NCF_HIDDEN = 0x0008 NCF_HIDDEN = 0x0008
NCF_NO_SERVICE = 0x0010 NCF_NO_SERVICE = 0x0010
NCF_NOT_USER_REMOVABLE = 0x0020 NCF_NOT_USER_REMOVABLE = 0x0020
NCF_HAS_UI = 0x0080 NCF_HAS_UI = 0x0080
NCF_MODEM = 0x0100 NCF_MODEM = 0x0100
; Registry types ; Registry types
REG_MULTI_SZ = 0x10000 REG_MULTI_SZ = 0x10000
REG_EXPAND_SZ = 0x20000 REG_EXPAND_SZ = 0x20000
REG_DWORD = 0x10001 REG_DWORD = 0x10001
; Win9x Compatible Types ; Win9x Compatible Types
REG_BINARY = 17 REG_BINARY = 17
REG_SZ = 0 REG_SZ = 0
; Service install flags ; Service install flags
SPSVCINST_TAGTOFRONT = 0x1 SPSVCINST_TAGTOFRONT = 0x1
SPSVCINST_ASSOCSERVICE = 0x2 SPSVCINST_ASSOCSERVICE = 0x2

View File

@ -1,142 +1,142 @@
; SkyWalker2Installer.INF -- This file installs SkyWalker2 Driver ; SkyWalker2Installer.INF -- This file installs SkyWalker2 Driver
; ;
[Version] [Version]
signature="$CHICAGO$" signature="$CHICAGO$"
Class=Media Class=Media
ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318} ClassGUID={4d36e96c-e325-11ce-bfc1-08002be10318}
Provider=%SGI% Provider=%SGI%
CatalogFile=SkyWalker2Installer.cat CatalogFile=SkyWalker2Installer.cat
DriverVer= 8/17/2009 DriverVer= 8/17/2009
; F i l e c o p y i n g s e c t i o n s (where the files go to). ; F i l e c o p y i n g s e c t i o n s (where the files go to).
; ;
[DestinationDirs] [DestinationDirs]
DefaultDestDir=10,system32\drivers DefaultDestDir=10,system32\drivers
[Manufacturer] [Manufacturer]
%SGI%=SGI %SGI%=SGI
[ControlFlags] [ControlFlags]
;ExcludeFromSelect=* ;ExcludeFromSelect=*
;ExcludeFromSelect.NT=* ;ExcludeFromSelect.NT=*
; =================== Generic ================================== ; =================== Generic ==================================
[SGI] [SGI]
%SkyWalker2.DeviceDesc%=SkyWalker2.Device,USB\VID_09C0&PID_0206 ;SkyWalker2 %SkyWalker2.DeviceDesc%=SkyWalker2.Device,USB\VID_09C0&PID_0206 ;SkyWalker2
[SkyWalker2.Device] [SkyWalker2.Device]
Include = ks.inf, kscaptur.inf, bda.inf Include = ks.inf, kscaptur.inf, bda.inf
needs = KS.Registration, KSCAPTUR.Registration, BDA.Installation needs = KS.Registration, KSCAPTUR.Registration, BDA.Installation
AddReg = SkyWalker2.AddReg AddReg = SkyWalker2.AddReg
CopyFiles = SkyWalker2.CopyDrivers CopyFiles = SkyWalker2.CopyDrivers
[SkyWalker2.Device.NT] [SkyWalker2.Device.NT]
Include = ks.inf, kscaptur.inf, bda.inf Include = ks.inf, kscaptur.inf, bda.inf
needs = KS.Registration.NT, KSCAPTUR.Registration.NT, BDA.Installation.NT needs = KS.Registration.NT, KSCAPTUR.Registration.NT, BDA.Installation.NT
;AddReg = SkyWalker2.AddReg ;AddReg = SkyWalker2.AddReg
CopyFiles = SkyWalker2.CopyDrivers CopyFiles = SkyWalker2.CopyDrivers
; KnownFiles = SkyWalker2.KnownFiles ; KnownFiles = SkyWalker2.KnownFiles
[SkyWalker2.Device.NT.Services] [SkyWalker2.Device.NT.Services]
Addservice=SkyWalker2TVTuner, 0x00000002, SkyWalker2.AddService Addservice=SkyWalker2TVTuner, 0x00000002, SkyWalker2.AddService
[SkyWalker2.AddService] [SkyWalker2.AddService]
DisplayName=%SkyWalker2.FriendlyName% DisplayName=%SkyWalker2.FriendlyName%
ServiceType=1 ; SERVICE_KERNEL_DRIVER ServiceType=1 ; SERVICE_KERNEL_DRIVER
StartType=3 ; SERVICE_DEMAND_START StartType=3 ; SERVICE_DEMAND_START
ErrorControl=1 ; SERVICE_ERROR_NORMAL ErrorControl=1 ; SERVICE_ERROR_NORMAL
ServiceBinary=%10%\System32\Drivers\SkyWalker1TVTuner.sys ServiceBinary=%10%\System32\Drivers\SkyWalker1TVTuner.sys
LoadOrderGroup=ExtendedBase LoadOrderGroup=ExtendedBase
[SkyWalker2.CopyDrivers] [SkyWalker2.CopyDrivers]
SkyWalker1TVTuner.sys SkyWalker1TVTuner.sys
[SkyWalker2.AddReg] [SkyWalker2.AddReg]
HKR,,DevLoader,,*NTKERN HKR,,DevLoader,,*NTKERN
HKR,,NTMPDriver,,SkyWalker1TVTuner.sys HKR,,NTMPDriver,,SkyWalker1TVTuner.sys
HKR,,PageOutWhenUnopened,3,01 HKR,,PageOutWhenUnopened,3,01
[SkyWalker2.Device.Interfaces] [SkyWalker2.Device.Interfaces]
AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,SkyWalker2.Receiver.Interfaces AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,SkyWalker2.Receiver.Interfaces
AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,SkyWalker2.Tuner.Interfaces AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,SkyWalker2.Tuner.Interfaces
[SkyWalker2.Device.NT.Interfaces] [SkyWalker2.Device.NT.Interfaces]
AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,SkyWalker2.Receiver.Interfaces AddInterface=%KSCATEGORY_BDA_RECEIVER_COMPONENT%,%SKYWALKER_CAPTURE%,SkyWalker2.Receiver.Interfaces
AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,SkyWalker2.Tuner.Interfaces AddInterface=%KSCATEGORY_BDA_NETWORK_TUNER%,%SKYWALKER_TUNER%,SkyWalker2.Tuner.Interfaces
[SkyWalker2.Tuner.Interfaces] [SkyWalker2.Tuner.Interfaces]
AddReg=SkyWalker2.Tuner.Interfaces.AddReg AddReg=SkyWalker2.Tuner.Interfaces.AddReg
[SkyWalker2.Tuner.Interfaces.AddReg] [SkyWalker2.Tuner.Interfaces.AddReg]
HKR,,CLSID,,%KSProxy.CLSID% HKR,,CLSID,,%KSProxy.CLSID%
HKR,,FriendlyName,,%SkyWalker2.Tuner.FriendlyName% HKR,,FriendlyName,,%SkyWalker2.Tuner.FriendlyName%
[SkyWalker2.Receiver.Interfaces] [SkyWalker2.Receiver.Interfaces]
AddReg=SkyWalker2.Receiver.Interfaces.AddReg AddReg=SkyWalker2.Receiver.Interfaces.AddReg
[SkyWalker2.Receiver.Interfaces.AddReg] [SkyWalker2.Receiver.Interfaces.AddReg]
HKR,,CLSID,,%KSProxy.CLSID% HKR,,CLSID,,%KSProxy.CLSID%
HKR,,FriendlyName,,%SkyWalker2.Receiver.FriendlyName% HKR,,FriendlyName,,%SkyWalker2.Receiver.FriendlyName%
[Strings] [Strings]
;non-localizable ;non-localizable
SGI="Plethorasoft" SGI="Plethorasoft"
MfgName="SGI" MfgName="SGI"
SkyWalker2.DeviceDesc="SkyWalker2 BDA TVTuner" SkyWalker2.DeviceDesc="SkyWalker2 BDA TVTuner"
SkyWalker2.Tuner.FriendlyName="SkyWalker2 TV Tuner" SkyWalker2.Tuner.FriendlyName="SkyWalker2 TV Tuner"
SkyWalker2.Receiver.FriendlyName="SkyWalker2 TV Receiver" SkyWalker2.Receiver.FriendlyName="SkyWalker2 TV Receiver"
SkyWalker2.Tuner="SkyWalker2.Tuner" SkyWalker2.Tuner="SkyWalker2.Tuner"
KSProxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}" KSProxy.CLSID="{17CCA71B-ECD7-11D0-B908-00A0C9223196}"
KSCATEGORY_BDA_NETWORK_TUNER="{71985F48-1CA1-11d3-9CC8-00C04F7971E0}" KSCATEGORY_BDA_NETWORK_TUNER="{71985F48-1CA1-11d3-9CC8-00C04F7971E0}"
KSCATEGORY_BDA_RECEIVER_COMPONENT="{FD0A5AF4-B41D-11d2-9C95-00C04F7971E0}" KSCATEGORY_BDA_RECEIVER_COMPONENT="{FD0A5AF4-B41D-11d2-9C95-00C04F7971E0}"
SKYWALKER_TUNER="{5C4E764F-AB43-46A9-B21E-8529C70F0A23}" SKYWALKER_TUNER="{5C4E764F-AB43-46A9-B21E-8529C70F0A23}"
SKYWALKER_CAPTURE="{0F8F74D9-E524-4D05-BB60-F0C69ACB1756}" SKYWALKER_CAPTURE="{0F8F74D9-E524-4D05-BB60-F0C69ACB1756}"
; ;
; ServiceType values ; ServiceType values
SERVICE_KERNEL_DRIVER = 0x00000001 SERVICE_KERNEL_DRIVER = 0x00000001
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002 SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
SERVICE_ADAPTER = 0x00000004 SERVICE_ADAPTER = 0x00000004
SERVICE_RECOGNIZER_DRIVER = 0x00000008 SERVICE_RECOGNIZER_DRIVER = 0x00000008
SERVICE_WIN32_OWN_PROCESS = 0x00000010 SERVICE_WIN32_OWN_PROCESS = 0x00000010
SERVICE_WIN32_SHARE_PROCESS = 0x00000020 SERVICE_WIN32_SHARE_PROCESS = 0x00000020
SERVICE_INTERACTIVE_PROCESS = 0x00000100 SERVICE_INTERACTIVE_PROCESS = 0x00000100
SERVICE_INTERACTIVE_SHARE_PROCESS = 0x00000120 SERVICE_INTERACTIVE_SHARE_PROCESS = 0x00000120
; StartType values ; StartType values
SERVICE_BOOT_START = 0x00000000 SERVICE_BOOT_START = 0x00000000
SERVICE_SYSTEM_START = 0x00000001 SERVICE_SYSTEM_START = 0x00000001
SERVICE_AUTO_START = 0x00000002 SERVICE_AUTO_START = 0x00000002
SERVICE_DEMAND_START = 0x00000003 SERVICE_DEMAND_START = 0x00000003
SERVICE_DISABLED = 0x00000004 SERVICE_DISABLED = 0x00000004
; ErrorControl values ; ErrorControl values
SERVICE_ERROR_IGNORE = 0x00000000 SERVICE_ERROR_IGNORE = 0x00000000
SERVICE_ERROR_NORMAL = 0x00000001 SERVICE_ERROR_NORMAL = 0x00000001
SERVICE_ERROR_SEVERE = 0x00000002 SERVICE_ERROR_SEVERE = 0x00000002
SERVICE_ERROR_CRITICAL = 0x00000003 SERVICE_ERROR_CRITICAL = 0x00000003
; Characteristic flags ; Characteristic flags
NCF_VIRTUAL = 0x0001 NCF_VIRTUAL = 0x0001
NCF_WRAPPER = 0x0002 NCF_WRAPPER = 0x0002
NCF_PHYSICAL = 0x0004 NCF_PHYSICAL = 0x0004
NCF_HIDDEN = 0x0008 NCF_HIDDEN = 0x0008
NCF_NO_SERVICE = 0x0010 NCF_NO_SERVICE = 0x0010
NCF_NOT_USER_REMOVABLE = 0x0020 NCF_NOT_USER_REMOVABLE = 0x0020
NCF_HAS_UI = 0x0080 NCF_HAS_UI = 0x0080
NCF_MODEM = 0x0100 NCF_MODEM = 0x0100
; Registry types ; Registry types
REG_MULTI_SZ = 0x10000 REG_MULTI_SZ = 0x10000
REG_EXPAND_SZ = 0x20000 REG_EXPAND_SZ = 0x20000
REG_DWORD = 0x10001 REG_DWORD = 0x10001
; Win9x Compatible Types ; Win9x Compatible Types
REG_BINARY = 17 REG_BINARY = 17
REG_SZ = 0 REG_SZ = 0
; Service install flags ; Service install flags
SPSVCINST_TAGTOFRONT = 0x1 SPSVCINST_TAGTOFRONT = 0x1
SPSVCINST_ASSOCSERVICE = 0x2 SPSVCINST_ASSOCSERVICE = 0x2

View File

@ -1,18 +1,18 @@
This firmware update utility will upgrade 8pSK-toUSB2 Rev.2 adapter firmware to ver.2.10.4 This firmware update utility will upgrade 8pSK-toUSB2 Rev.2 adapter firmware to ver.2.10.4
############################################################################################################## ##############################################################################################################
# #
# Make sure that genpix 8pSK-toUSB2 Rev.2 adapter is the ONLY genpix device connected to PC during firmware upgrade. # Make sure that genpix 8pSK-toUSB2 Rev.2 adapter is the ONLY genpix device connected to PC during firmware upgrade.
# Disconnect all other genpix devices. # Disconnect all other genpix devices.
# #
# 8PSK module has to be connected to adapter during firmware upgrade procedure. # 8PSK module has to be connected to adapter during firmware upgrade procedure.
# #
# Do NOT switch the PC power off during firmware upgrade procedure. # Do NOT switch the PC power off during firmware upgrade procedure.
# Do NOT plug/unplug any USB devices during firmware upgrade procedure. # Do NOT plug/unplug any USB devices during firmware upgrade procedure.
# #
############################################################################################################## ##############################################################################################################
8pSK-toUSB2 Rev.2 adapter firmware updater runs in Windows x32/x64 environment only (Windows XP and higher). 8pSK-toUSB2 Rev.2 adapter firmware updater runs in Windows x32/x64 environment only (Windows XP and higher).
To start firmware upgrade: To start firmware upgrade:
double-click on Rev2_update_2_10_4.exe file, and follow the instruction on the screen. double-click on Rev2_update_2_10_4.exe file, and follow the instruction on the screen.

View File

@ -1,379 +1,379 @@
# Genpix SkyWalker-1 Firmware v2.13.x Sub-Variant Comparison Report # Genpix SkyWalker-1 Firmware v2.13.x Sub-Variant Comparison Report
## Executive Summary ## Executive Summary
Three firmware sub-variants were extracted from `SW1_update_2_13_x.exe` and analyzed as 8051 (Cypress FX2) binaries via Ghidra. The analysis reveals that **FW1 (v2.13.1) targets fundamentally different hardware** than FW2/FW3, while **FW2 (v2.13.2) and FW3 (v2.13.3) target different revisions of a newer hardware platform** with an external demodulator connected via a parallel data bus. Three firmware sub-variants were extracted from `SW1_update_2_13_x.exe` and analyzed as 8051 (Cypress FX2) binaries via Ghidra. The analysis reveals that **FW1 (v2.13.1) targets fundamentally different hardware** than FW2/FW3, while **FW2 (v2.13.2) and FW3 (v2.13.3) target different revisions of a newer hardware platform** with an external demodulator connected via a parallel data bus.
--- ---
## 1. Function List Comparison ## 1. Function List Comparison
### Function Counts ### Function Counts
| Variant | Port | Functions | Extra Function | | Variant | Port | Functions | Extra Function |
|---------|------|-----------|----------------| |---------|------|-----------|----------------|
| FW1 (v2.13.1) | 8194 | 82 | FUN_CODE_0fc7, FUN_CODE_1405, FUN_CODE_14b9 (unique) | | FW1 (v2.13.1) | 8194 | 82 | FUN_CODE_0fc7, FUN_CODE_1405, FUN_CODE_14b9 (unique) |
| FW2 (v2.13.2) | 8195 | 83 | FUN_CODE_1288 (unique), FUN_CODE_0ffc | | FW2 (v2.13.2) | 8195 | 83 | FUN_CODE_1288 (unique), FUN_CODE_0ffc |
| FW3 (v2.13.3) | 8196 | 83 | FUN_CODE_1288, FUN_CODE_0706 (unique) | | FW3 (v2.13.3) | 8196 | 83 | FUN_CODE_1288, FUN_CODE_0706 (unique) |
### Shared Core Functions (Same Address Across All Three) ### Shared Core Functions (Same Address Across All Three)
The following functions exist at identical addresses in all variants: The following functions exist at identical addresses in all variants:
``` ```
CODE:0000 RESET_vector CODE:0003 INT0_vector CODE:0000 RESET_vector CODE:0003 INT0_vector
CODE:0033 INT2_USB_GPIF_vector CODE:0036 FUN_CODE_0036 CODE:0033 INT2_USB_GPIF_vector CODE:0036 FUN_CODE_0036
CODE:0043 INT4_FX2_vector CODE:004b INT5_FX2_vector CODE:0043 INT4_FX2_vector CODE:004b INT5_FX2_vector
CODE:0050 FUN_CODE_0050 CODE:0053 INT6_FX2_vector CODE:0050 FUN_CODE_0050 CODE:0053 INT6_FX2_vector
CODE:0056 FUN_CODE_0056 CODE:034e FUN_CODE_034e (vendor cmd handler) CODE:0056 FUN_CODE_0056 CODE:034e FUN_CODE_034e (vendor cmd handler)
CODE:06d9 FUN_CODE_06d9 CODE:0718 FUN_CODE_0718 CODE:06d9 FUN_CODE_06d9 CODE:0718 FUN_CODE_0718
CODE:072a FUN_CODE_072a CODE:0779 FUN_CODE_0779 CODE:072a FUN_CODE_072a CODE:0779 FUN_CODE_0779
CODE:079d FUN_CODE_079d CODE:0800 FUN_CODE_0800 (main loop) CODE:079d FUN_CODE_079d CODE:0800 FUN_CODE_0800 (main loop)
CODE:0ca4 FUN_CODE_0ca4 CODE:0eea FUN_CODE_0eea CODE:0ca4 FUN_CODE_0ca4 CODE:0eea FUN_CODE_0eea
CODE:1000 FUN_CODE_1000 CODE:1500 thunk (target differs!) CODE:1000 FUN_CODE_1000 CODE:1500 thunk (target differs!)
CODE:15b8 FUN_CODE_15b8 CODE:170d main_entry CODE:15b8 FUN_CODE_15b8 CODE:170d main_entry
CODE:1799 FUN_CODE_1799 CODE:1800 FUN_CODE_1800 CODE:1799 FUN_CODE_1799 CODE:1800 FUN_CODE_1800
CODE:19ed FUN_CODE_19ed CODE:1a5d FUN_CODE_1a5d CODE:19ed FUN_CODE_19ed CODE:1a5d FUN_CODE_1a5d
CODE:1ac6 FUN_CODE_1ac6 CODE:1b2a FUN_CODE_1b2a CODE:1ac6 FUN_CODE_1ac6 CODE:1b2a FUN_CODE_1b2a
``` ```
### Functions That Shift Addresses (Same Logic, Different Location) ### Functions That Shift Addresses (Same Logic, Different Location)
Many functions exist in all three variants but at shifted addresses: Many functions exist in all three variants but at shifted addresses:
| Purpose | FW1 Address | FW2 Address | FW3 Address | | Purpose | FW1 Address | FW2 Address | FW3 Address |
|---------|-------------|-------------|-------------| |---------|-------------|-------------|-------------|
| Hardware init | 0x11ab | 0x1288 | 0x1288 | | Hardware init | 0x11ab | 0x1288 | 0x1288 |
| Demod setup | 0x10d9 | 0x10dd | 0x10dd | | Demod setup | 0x10d9 | 0x10dd | 0x10dd |
| I2C/parallel data transfer | 0x0eea (I2C) | 0x0eea (parallel) | 0x0eea (parallel) | | I2C/parallel data transfer | 0x0eea (I2C) | 0x0eea (parallel) | 0x0eea (parallel) |
| Tuner detect | 0x1405 | 0x0eea | 0x0eea | | Tuner detect | 0x1405 | 0x0eea | 0x0eea |
| Delay loop | 0x14b9 | 0x1e92 (FW2) | 0x1e88 (FW3) | | Delay loop | 0x14b9 | 0x1e92 (FW2) | 0x1e88 (FW3) |
| EEPROM checksum | 0x1ca0 | 0x1cff | 0x1ca1 | | EEPROM checksum | 0x1ca0 | 0x1cff | 0x1ca1 |
| USB descriptor setup | 0x2031 | 0x206c | 0x206c | | USB descriptor setup | 0x2031 | 0x206c | 0x206c |
| Thunk target | 0x2252 | 0x228d | 0x228d | | Thunk target | 0x2252 | 0x228d | 0x228d |
| 2nd init call | 0x1be6 | 0x1c45 | 0x1cf7 | | 2nd init call | 0x1be6 | 0x1c45 | 0x1cf7 |
### Functions Unique to Each Variant ### Functions Unique to Each Variant
**FW1 only:** **FW1 only:**
- `FUN_CODE_0fc7` -- An I2C write-with-retry function (tries 0x14 = 20 times via I2C bus using FUN_CODE_23ae/23ee) - `FUN_CODE_0fc7` -- An I2C write-with-retry function (tries 0x14 = 20 times via I2C bus using FUN_CODE_23ae/23ee)
- `FUN_CODE_1405` -- Tuner/demodulator identification via **I2C bus + P1 port reads** with signature matching - `FUN_CODE_1405` -- Tuner/demodulator identification via **I2C bus + P1 port reads** with signature matching
- `FUN_CODE_14b9` -- Calibrated delay function using CPUCS clock divider awareness - `FUN_CODE_14b9` -- Calibrated delay function using CPUCS clock divider awareness
**FW2 only:** **FW2 only:**
- `FUN_CODE_0ffc` -- Stores a parameter into BANK3_R1 (register save) - `FUN_CODE_0ffc` -- Stores a parameter into BANK3_R1 (register save)
- `FUN_CODE_1288` -- New hardware initialization (loads from external memory at e080-e08e) - `FUN_CODE_1288` -- New hardware initialization (loads from external memory at e080-e08e)
**FW3 only:** **FW3 only:**
- `FUN_CODE_0706` -- Memory write dispatcher that handles 3 addressing modes (XDATA, IDATA, direct) - `FUN_CODE_0706` -- Memory write dispatcher that handles 3 addressing modes (XDATA, IDATA, direct)
- `FUN_CODE_1288` -- Same as FW2 - `FUN_CODE_1288` -- Same as FW2
- Uses `FUN_CODE_1ffc` (at a different address from FW2's 0x1ffd) - Uses `FUN_CODE_1ffc` (at a different address from FW2's 0x1ffd)
--- ---
## 2. Main Entry Comparison (CODE:170D) ## 2. Main Entry Comparison (CODE:170D)
### Identical Across All Three: ### Identical Across All Three:
- IRAM clear loop (0x7F down to 0x00) - IRAM clear loop (0x7F down to 0x00)
- Init table parsing from CODE:0B88 - Init table parsing from CODE:0B88
- Bit config table reference at CODE:1740 - Bit config table reference at CODE:1740
- Final call to FUN_CODE_0800 - Final call to FUN_CODE_0800
### One Key Difference -- Stack Pointer: ### One Key Difference -- Stack Pointer:
| Variant | SP Value | | Variant | SP Value |
|---------|----------| |---------|----------|
| FW1 | SP = 0x50 | | FW1 | SP = 0x50 |
| FW2 | SP = 0x50 | | FW2 | SP = 0x50 |
| FW3 | SP = **0x52** | | FW3 | SP = **0x52** |
FW3 sets `SP = 0x52`, requiring 2 more bytes of IRAM for stack usage. This indicates FW3 uses additional internal RAM locations (0x51-0x52) for state variables that FW1/FW2 don't need, pushing the stack higher. FW3 sets `SP = 0x52`, requiring 2 more bytes of IRAM for stack usage. This indicates FW3 uses additional internal RAM locations (0x51-0x52) for state variables that FW1/FW2 don't need, pushing the stack higher.
**Confirmed**: FW3 uses `DAT_INTMEM_51` as a hardware status register throughout its code, while FW1/FW2 use `DAT_INTMEM_4f` for the same purpose. The 2-byte difference in SP exactly accounts for this. **Confirmed**: FW3 uses `DAT_INTMEM_51` as a hardware status register throughout its code, while FW1/FW2 use `DAT_INTMEM_4f` for the same purpose. The 2-byte difference in SP exactly accounts for this.
### Memory at CODE:170D: ### Memory at CODE:170D:
``` ```
FW1: 787f e4f6 d8fd 7581 50 02 1754 020800 e4 FW1: 787f e4f6 d8fd 7581 50 02 1754 020800 e4
FW2: 787f e4f6 d8fd 7581 50 02 1754 020800 e4 (identical to FW1) FW2: 787f e4f6 d8fd 7581 50 02 1754 020800 e4 (identical to FW1)
FW3: 787f e4f6 d8fd 7581 52 02 1754 020800 e4 (byte at 0x1714 = 0x52 vs 0x50) FW3: 787f e4f6 d8fd 7581 52 02 1754 020800 e4 (byte at 0x1714 = 0x52 vs 0x50)
``` ```
--- ---
## 3. Key Function Decompilation Comparison ## 3. Key Function Decompilation Comparison
### 3.1 FUN_CODE_0800 (Main Loop) -- All at Same Address ### 3.1 FUN_CODE_0800 (Main Loop) -- All at Same Address
**Structure identical across all three:** **Structure identical across all three:**
1. Clear INTMEM locations 0x22-0x2D, 0x32-0x35 1. Clear INTMEM locations 0x22-0x2D, 0x32-0x35
2. Clear bit flags _1_0 and _0_6 2. Clear bit flags _1_0 and _0_6
3. Call hardware init (address differs) 3. Call hardware init (address differs)
4. Set up BANK register pairs (XDATA pointers): all use the same values (0x0E00, 0x0E12, 0x0E1C, 0x0E54, 0x0E8C, 0x0EE8) 4. Set up BANK register pairs (XDATA pointers): all use the same values (0x0E00, 0x0E12, 0x0E1C, 0x0E54, 0x0E8C, 0x0EE8)
5. Call FUN_CODE_072a with init params 5. Call FUN_CODE_072a with init params
6. Memory copy loop (0x80 bytes at offset 0x0E00) 6. Memory copy loop (0x80 bytes at offset 0x0E00)
7. Retry loop with FUN_CODE_1799 (20 attempts) 7. Retry loop with FUN_CODE_1799 (20 attempts)
8. Retry loop with EEPROM checksum function (20 attempts) 8. Retry loop with EEPROM checksum function (20 attempts)
9. Check demod type byte at offset +10 from BANK1_R4/R5 (== 0x03 -> set flag) 9. Check demod type byte at offset +10 from BANK1_R4/R5 (== 0x03 -> set flag)
10. Enable interrupts, enter main event loop 10. Enable interrupts, enter main event loop
**Differences in called function addresses (relocated, not functionally different):** **Differences in called function addresses (relocated, not functionally different):**
| Call Purpose | FW1 | FW2 | FW3 | | Call Purpose | FW1 | FW2 | FW3 |
|-------------|------|------|------| |-------------|------|------|------|
| Hardware init | FUN_CODE_11ab | FUN_CODE_1288 | FUN_CODE_1288 | | Hardware init | FUN_CODE_11ab | FUN_CODE_1288 | FUN_CODE_1288 |
| EEPROM checksum | FUN_CODE_1ca0 | FUN_CODE_1cff | FUN_CODE_1ca1 | | EEPROM checksum | FUN_CODE_1ca0 | FUN_CODE_1cff | FUN_CODE_1ca1 |
| USB setup | FUN_CODE_2031 | FUN_CODE_206c | FUN_CODE_206c | | USB setup | FUN_CODE_2031 | FUN_CODE_206c | FUN_CODE_206c |
| Main loop poll | FUN_CODE_21ec | FUN_CODE_2227 | FUN_CODE_2227 | | Main loop poll | FUN_CODE_21ec | FUN_CODE_2227 | FUN_CODE_2227 |
| Interrupt check | FUN_CODE_2445 | FUN_CODE_247c | FUN_CODE_2473 | | Interrupt check | FUN_CODE_2445 | FUN_CODE_247c | FUN_CODE_2473 |
| Status check | FUN_CODE_2189 | FUN_CODE_21c4 | FUN_CODE_21c4 | | Status check | FUN_CODE_2189 | FUN_CODE_21c4 | FUN_CODE_21c4 |
| Buffer flush | FUN_CODE_20b9 | FUN_CODE_20f4 | FUN_CODE_20f4 | | Buffer flush | FUN_CODE_20b9 | FUN_CODE_20f4 | FUN_CODE_20f4 |
| EP complete | FUN_CODE_2447 | FUN_CODE_247e | FUN_CODE_2475 | | EP complete | FUN_CODE_2447 | FUN_CODE_247e | FUN_CODE_2475 |
### 3.2 Hardware Init Function (FW1: 0x11ab, FW2/FW3: 0x1288) ### 3.2 Hardware Init Function (FW1: 0x11ab, FW2/FW3: 0x1288)
**Functionally identical** across all three except: **Functionally identical** across all three except:
| Parameter | FW1 | FW2 | FW3 | | Parameter | FW1 | FW2 | FW3 |
|-----------|------|------|------| |-----------|------|------|------|
| P0 init value | **0xa4** | **0xa4** | **0xa0** | | P0 init value | **0xa4** | **0xa4** | **0xa0** |
| Status register | DAT_INTMEM_4f | DAT_INTMEM_4f | **DAT_INTMEM_51** | | Status register | DAT_INTMEM_4f | DAT_INTMEM_4f | **DAT_INTMEM_51** |
| Sub-init call 1 | FUN_CODE_1c44 | FUN_CODE_1ca3 | FUN_CODE_1c45 | | Sub-init call 1 | FUN_CODE_1c44 | FUN_CODE_1ca3 | FUN_CODE_1c45 |
| Sub-init call 2 | FUN_CODE_1000 | FUN_CODE_10dd | FUN_CODE_10dd | | Sub-init call 2 | FUN_CODE_1000 | FUN_CODE_10dd | FUN_CODE_10dd |
| I2C/bus init | FUN_CODE_213b | FUN_CODE_2176 | FUN_CODE_2176 | | I2C/bus init | FUN_CODE_213b | FUN_CODE_2176 | FUN_CODE_2176 |
| Tuner init | FUN_CODE_1be6 | FUN_CODE_1c45 | FUN_CODE_1cf7 | | Tuner init | FUN_CODE_1be6 | FUN_CODE_1c45 | FUN_CODE_1cf7 |
**P0 = 0xa4 vs 0xa0**: P0 on the FX2 controls GPIO port 0. The difference is bit 2: **P0 = 0xa4 vs 0xa0**: P0 on the FX2 controls GPIO port 0. The difference is bit 2:
- FW1/FW2: P0 bit 2 = 1 (0xa4 = 1010 0100) - FW1/FW2: P0 bit 2 = 1 (0xa4 = 1010 0100)
- FW3: P0 bit 2 = 0 (0xa0 = 1010 0000) - FW3: P0 bit 2 = 0 (0xa0 = 1010 0000)
This suggests different default GPIO state for a control signal, likely related to the demodulator interface mode or reset polarity. This suggests different default GPIO state for a control signal, likely related to the demodulator interface mode or reset polarity.
### 3.3 FUN_CODE_0eea -- The Most Revealing Difference ### 3.3 FUN_CODE_0eea -- The Most Revealing Difference
**FW1**: This is a standard **I2C master transfer** function: **FW1**: This is a standard **I2C master transfer** function:
- Uses `FUN_CODE_23ae` (I2C START), `FUN_CODE_23ee` (I2C byte write), `FUN_CODE_23d0` (I2C address) - Uses `FUN_CODE_23ae` (I2C START), `FUN_CODE_23ee` (I2C byte write), `FUN_CODE_23d0` (I2C address)
- Reads back via `FUN_CODE_2164` - Reads back via `FUN_CODE_2164`
- Standard I2C retry with NACK detection - Standard I2C retry with NACK detection
**FW2**: This is a **parallel bus read with demodulator handshake**: **FW2**: This is a **parallel bus read with demodulator handshake**:
- Reads demod type from address table (BANK1_R4/R5 + offset) - Reads demod type from address table (BANK1_R4/R5 + offset)
- Uses `FUN_CODE_11b6` for demod selection - Uses `FUN_CODE_11b6` for demod selection
- Toggles P0 bits 6/7 for bus control (P0.6 = chip select, P0.7 = read strobe) - Toggles P0 bits 6/7 for bus control (P0.6 = chip select, P0.7 = read strobe)
- Reads data from P1 port (parallel data bus) - Reads data from P1 port (parallel data bus)
- Checks P1 ^ 0x1D (signature) then reads P1 for device ID - Checks P1 ^ 0x1D (signature) then reads P1 for device ID
- Matches device IDs: 0xC5/0xD5 (for type 3), 0x5A (type 4), 0x5B (type 5), 0x5C (type 6) - Matches device IDs: 0xC5/0xD5 (for type 3), 0x5A (type 4), 0x5B (type 5), 0x5C (type 6)
- Controls P3 bits for demod power/reset - Controls P3 bits for demod power/reset
**FW3**: Similar parallel bus read as FW2 but with **different timing and bus protocol**: **FW3**: Similar parallel bus read as FW2 but with **different timing and bus protocol**:
- Sets P0 | 0x80 once at start (not per-iteration like FW2) - Sets P0 | 0x80 once at start (not per-iteration like FW2)
- Uses `DAT_INTMEM_3f` and `DAT_INTMEM_40` as OR-accumulators for P1 reads - Uses `DAT_INTMEM_3f` and `DAT_INTMEM_40` as OR-accumulators for P1 reads
- Two separate P1 reads per cycle: one with P0.6 high, one with P0.6 low - Two separate P1 reads per cycle: one with P0.6 high, one with P0.6 low
- Calls `FUN_CODE_1b2a` with 3 parameters (accumulated OR values) vs FW2's 2 parameters - Calls `FUN_CODE_1b2a` with 3 parameters (accumulated OR values) vs FW2's 2 parameters
- Uses `P0 | 0x44` and `P0 & 0xBF` toggle pattern (vs FW2's different bit dance) - Uses `P0 | 0x44` and `P0 & 0xBF` toggle pattern (vs FW2's different bit dance)
### 3.4 Vendor Command Handler (FUN_CODE_034e) ### 3.4 Vendor Command Handler (FUN_CODE_034e)
**Structurally identical** across all three -- same switch/case table structure at CODE:035e. **Structurally identical** across all three -- same switch/case table structure at CODE:035e.
Key differences: Key differences:
| Feature | FW1 | FW2 | FW3 | | Feature | FW1 | FW2 | FW3 |
|---------|------|------|------| |---------|------|------|------|
| Case 0x35f/0x427 call | FUN_CODE_0ffe (nop) | FUN_CODE_1ffd | FUN_CODE_0ffe (nop) | | Case 0x35f/0x427 call | FUN_CODE_0ffe (nop) | FUN_CODE_1ffd | FUN_CODE_0ffe (nop) |
| Case 0x361 call | FUN_CODE_2441 | FUN_CODE_2478 | FUN_CODE_246f | | Case 0x361 call | FUN_CODE_2441 | FUN_CODE_2478 | FUN_CODE_246f |
| Case 0x365 call | FUN_CODE_2443 | FUN_CODE_247a | FUN_CODE_2471 | | Case 0x365 call | FUN_CODE_2443 | FUN_CODE_247a | FUN_CODE_2471 |
| Case 0x36f call | FUN_CODE_2357 | FUN_CODE_2392 | FUN_CODE_2392 | | Case 0x36f call | FUN_CODE_2357 | FUN_CODE_2392 | FUN_CODE_2392 |
| Case 0x371 call | FUN_CODE_243d | FUN_CODE_0ffc | FUN_CODE_1ffc | | Case 0x371 call | FUN_CODE_243d | FUN_CODE_0ffc | FUN_CODE_1ffc |
| Case 0x373/0x3ff call | FUN_CODE_2309 | FUN_CODE_2344 | FUN_CODE_2344 | | Case 0x373/0x3ff call | FUN_CODE_2309 | FUN_CODE_2344 | FUN_CODE_2344 |
| Case 0xf0 indirect call | func_0x231e | func_0x2359 | func_0x2359 | | Case 0xf0 indirect call | func_0x231e | func_0x2359 | func_0x2359 |
| Case 0x39d return | func_0x06e4 | DAT=0x0 | DAT=0x0 | | Case 0x39d return | func_0x06e4 | DAT=0x0 | DAT=0x0 |
| Case 0x3d1 call | FUN_CODE_2110 | FUN_CODE_214b | FUN_CODE_214b | | Case 0x3d1 call | FUN_CODE_2110 | FUN_CODE_214b | FUN_CODE_214b |
| Case 0x3d3 behavior | TR2 timer check | OR operation | OR operation | | Case 0x3d3 behavior | TR2 timer check | OR operation | OR operation |
| Case 0x405 behavior | Goto LAB_05db | Conditional branch | Conditional branch | | Case 0x405 behavior | Goto LAB_05db | Conditional branch | Conditional branch |
| Case 0x421 behavior | Simple check | Extra P2_1, RL A logic | Extra P2_1, RL A logic | | Case 0x421 behavior | Simple check | Extra P2_1, RL A logic | Extra P2_1, RL A logic |
**FW1's unique case 0x3d3**: Checks Timer 2 Run flag (TR2) -- this is used for I2C bus timeout recovery, consistent with FW1 being I2C-based. **FW1's unique case 0x3d3**: Checks Timer 2 Run flag (TR2) -- this is used for I2C bus timeout recovery, consistent with FW1 being I2C-based.
**FW2/FW3's unique case 0x421-0x423**: Includes a rotate-left and P2.1 write -- this is a parallel bus data direction control, consistent with the external demodulator interface. **FW2/FW3's unique case 0x421-0x423**: Includes a rotate-left and P2.1 write -- this is a parallel bus data direction control, consistent with the external demodulator interface.
--- ---
## 4. Memory Comparison at Key Offsets ## 4. Memory Comparison at Key Offsets
### CODE:0000-0x000F (Reset Vector) ### CODE:0000-0x000F (Reset Vector)
``` ```
FW1: 02170d 753728 e53760 1b7ffc 7e7f12 22 FW1: 02170d 753728 e53760 1b7ffc 7e7f12 22
FW2: 02170d 753728 e53760 1b7ffc 7e7f12 22 FW2: 02170d 753728 e53760 1b7ffc 7e7f12 22
FW3: 02170d 753728 e53760 1b7ffc 7e7f12 22 FW3: 02170d 753728 e53760 1b7ffc 7e7f12 22
ALL IDENTICAL -- LJMP 0x170D, then INT0 vector handler ALL IDENTICAL -- LJMP 0x170D, then INT0 vector handler
``` ```
### CODE:0B88-0x0B9F (Init Table Start) ### CODE:0B88-0x0B9F (Init Table Start)
``` ```
FW1: 41e0b6 626033 e0c609 070939 4f0000 000000 000000 000000 FW1: 41e0b6 626033 e0c609 070939 4f0000 000000 000000 000000
FW2: 41e0b6 626033 e0c609 070939 4f0000 000000 000000 000000 FW2: 41e0b6 626033 e0c609 070939 4f0000 000000 000000 000000
FW3: 41e0b6 626033 e0c609 070939 4f0000 000000 000000 000000 FW3: 41e0b6 626033 e0c609 070939 4f0000 000000 000000 000000
ALL IDENTICAL -- Same register/SFR initialization table ALL IDENTICAL -- Same register/SFR initialization table
``` ```
### CODE:1500 (Thunk/INT Vector Target) ### CODE:1500 (Thunk/INT Vector Target)
``` ```
FW1: 02 2252 00 02 22dd 00 02 22c7 00 02 226a 00 FW1: 02 2252 00 02 22dd 00 02 22c7 00 02 226a 00
FW2: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00 FW2: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00
FW3: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00 FW3: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00
``` ```
FW1 jumps to different addresses than FW2/FW3. **FW2 and FW3 are IDENTICAL here** -- their interrupt handlers are at the same addresses. FW1 jumps to different addresses than FW2/FW3. **FW2 and FW3 are IDENTICAL here** -- their interrupt handlers are at the same addresses.
### CODE:1740-0x174F (Bit Config Table) ### CODE:1740-0x174F (Bit Config Table)
``` ```
FW1: 4004 f456 8001 46f6 dfe4 800b 0102 0408 FW1: 4004 f456 8001 46f6 dfe4 800b 0102 0408
FW2: 4004 f456 8001 46f6 dfe4 800b 0102 0408 FW2: 4004 f456 8001 46f6 dfe4 800b 0102 0408
FW3: 4004 f456 8001 46f6 dfe4 800b 0102 0408 FW3: 4004 f456 8001 46f6 dfe4 800b 0102 0408
ALL IDENTICAL -- Same bit manipulation lookup table ALL IDENTICAL -- Same bit manipulation lookup table
``` ```
### CODE:0800 (Main Loop Start) ### CODE:0800 (Main Loop Start)
``` ```
FW1: e4f52d...c208c206 12 11ab 750c0e... FW1: e4f52d...c208c206 12 11ab 750c0e...
FW2: e4f52d...c208c206 12 1288 750c0e... FW2: e4f52d...c208c206 12 1288 750c0e...
FW3: e4f52d...c208c206 12 1288 750c0e... FW3: e4f52d...c208c206 12 1288 750c0e...
``` ```
Only difference: the LCALL target (FW1: 0x11ab, FW2/FW3: 0x1288). Only difference: the LCALL target (FW1: 0x11ab, FW2/FW3: 0x1288).
### CODE:06D9 (Utility Functions) ### CODE:06D9 (Utility Functions)
``` ```
FW1: bb010c e58229 f582e5 833af5 83e022 5006e9 2582f8 e622 FW1: bb010c e58229 f582e5 833af5 83e022 5006e9 2582f8 e622
FW2: bb010c e58229 f582e5 833af5 83e022 5006e9 2582f8 e622 FW2: bb010c e58229 f582e5 833af5 83e022 5006e9 2582f8 e622
FW3: bb010c e58229 f582e5 833af5 83e022 5006e9 2582f8 e622 FW3: bb010c e58229 f582e5 833af5 83e022 5006e9 2582f8 e622
ALL IDENTICAL -- Generic memory access utilities shared by all ALL IDENTICAL -- Generic memory access utilities shared by all
``` ```
### CODE:0EEA (Critical Divergence Point) ### CODE:0EEA (Critical Divergence Point)
``` ```
FW1: 8f44 8c45 8d46 8b47 754a14 e544 b451... (I2C transfer params in registers) FW1: 8f44 8c45 8d46 8b47 754a14 e544 b451... (I2C transfer params in registers)
FW2: 753e14 e50d 240a f582 e435 0cf5 83e0... (reads from DPTR+offset table) FW2: 753e14 e50d 240a f582 e435 0cf5 83e0... (reads from DPTR+offset table)
FW3: 753e14 e4f5 3ff5 40 e50d 240a f582... (similar to FW2 + accumulator init) FW3: 753e14 e4f5 3ff5 40 e50d 240a f582... (similar to FW2 + accumulator init)
``` ```
This confirms: FW1's FUN_CODE_0eea is a completely different function (I2C master) than FW2/FW3's (parallel bus demod interface). This confirms: FW1's FUN_CODE_0eea is a completely different function (I2C master) than FW2/FW3's (parallel bus demod interface).
--- ---
## 5. FW2 vs FW3 Specific Differences ## 5. FW2 vs FW3 Specific Differences
FW2 and FW3 are the most similar pair (1,525 bytes different). Key differences: FW2 and FW3 are the most similar pair (1,525 bytes different). Key differences:
| Feature | FW2 | FW3 | | Feature | FW2 | FW3 |
|---------|------|------| |---------|------|------|
| Stack Pointer | SP = 0x50 | SP = 0x52 | | Stack Pointer | SP = 0x50 | SP = 0x52 |
| Status register | DAT_INTMEM_4f | DAT_INTMEM_51 | | Status register | DAT_INTMEM_4f | DAT_INTMEM_51 |
| P0 init | 0xa4 | 0xa0 (bit 2 different) | | P0 init | 0xa4 | 0xa0 (bit 2 different) |
| FUN_CODE_0eea bus protocol | Single-phase P1 read | Dual-phase P1 read with OR accumulation | | FUN_CODE_0eea bus protocol | Single-phase P1 read | Dual-phase P1 read with OR accumulation |
| I2C buffer addresses | DAT_INTMEM_48/49 | DAT_INTMEM_4a/4b | | I2C buffer addresses | DAT_INTMEM_48/49 | DAT_INTMEM_4a/4b |
| Unique function | FUN_CODE_0ffc (register store) | FUN_CODE_0706 (multi-mode write) | | Unique function | FUN_CODE_0ffc (register store) | FUN_CODE_0706 (multi-mode write) |
| P0 bus timing | P0 &= ~0x40; P0 |= 0x80 per iteration | P0 |= 0x80 once; P0 |= 0x44 / P0 &= ~0x40 per phase | | P0 bus timing | P0 &= ~0x40; P0 |= 0x80 per iteration | P0 |= 0x80 once; P0 |= 0x44 / P0 &= ~0x40 per phase |
| Delay function address | FUN_CODE_1e92 | FUN_CODE_1e88 | | Delay function address | FUN_CODE_1e92 | FUN_CODE_1e88 |
### The P1 Read Difference is Critical ### The P1 Read Difference is Critical
**FW2** reads P1 once per bus cycle: **FW2** reads P1 once per bus cycle:
```c ```c
uVar1 = P1; // Read with one bus state uVar1 = P1; // Read with one bus state
P0 |= 0x40; // Then change control line P0 |= 0x40; // Then change control line
uVar2 = P1; // Read again uVar2 = P1; // Read again
FUN_CODE_1b2a(uVar2, uVar1); // Process both samples FUN_CODE_1b2a(uVar2, uVar1); // Process both samples
``` ```
**FW3** reads P1 in two phases and OR-accumulates: **FW3** reads P1 in two phases and OR-accumulates:
```c ```c
DAT_INTMEM_3f = 0; DAT_INTMEM_40 = 0; // Clear accumulators DAT_INTMEM_3f = 0; DAT_INTMEM_40 = 0; // Clear accumulators
// Phase 1: P0.6 high // Phase 1: P0.6 high
P0 |= 0x44; P0 |= 0x44;
bVar2 = P1; bVar2 = P1;
DAT_INTMEM_3f |= bVar2; // OR-accumulate DAT_INTMEM_3f |= bVar2; // OR-accumulate
// Phase 2: P0.6 low // Phase 2: P0.6 low
P0 &= ~0x40; P0 &= ~0x40;
bVar2 = P1; bVar2 = P1;
DAT_INTMEM_40 |= bVar2; // OR-accumulate DAT_INTMEM_40 |= bVar2; // OR-accumulate
FUN_CODE_1b2a(0, DAT_INTMEM_3f, DAT_INTMEM_40); // Process accumulated FUN_CODE_1b2a(0, DAT_INTMEM_3f, DAT_INTMEM_40); // Process accumulated
``` ```
This OR-accumulation pattern in FW3 suggests dealing with a bus that may have metastable signals or requires multiple samples, characteristic of **a different demodulator chip with different bus timing**. This OR-accumulation pattern in FW3 suggests dealing with a bus that may have metastable signals or requires multiple samples, characteristic of **a different demodulator chip with different bus timing**.
--- ---
## 6. Hypothesis: What Distinguishes Each Variant ## 6. Hypothesis: What Distinguishes Each Variant
### FW1 (v2.13.1) -- Original I2C-Connected Demodulator Hardware ### FW1 (v2.13.1) -- Original I2C-Connected Demodulator Hardware
**Target**: First-generation SkyWalker-1 PCB with an **I2C-connected demodulator** (likely a Conexant/Zarlink integrated tuner+demod). **Target**: First-generation SkyWalker-1 PCB with an **I2C-connected demodulator** (likely a Conexant/Zarlink integrated tuner+demod).
Evidence: Evidence:
- Uses standard I2C protocol functions (START, STOP, ACK/NACK, byte read/write) - Uses standard I2C protocol functions (START, STOP, ACK/NACK, byte read/write)
- FUN_CODE_0fc7: I2C write retry loop - FUN_CODE_0fc7: I2C write retry loop
- FUN_CODE_1405: Reads demodulator identification via I2C + P1 GPIO, checks device signatures: - FUN_CODE_1405: Reads demodulator identification via I2C + P1 GPIO, checks device signatures:
- Type 3: P1 == 0xA5 or 0xB5 - Type 3: P1 == 0xA5 or 0xB5
- Type 4: P1 == 0x5A - Type 4: P1 == 0x5A
- Type 5: P1 == 0x5B - Type 5: P1 == 0x5B
- Type 6: P1 == 0x5C - Type 6: P1 == 0x5C
- Has timer-based I2C timeout (TR2 check in vendor handler) - Has timer-based I2C timeout (TR2 check in vendor handler)
- SP=0x50, fewer IRAM state variables needed - SP=0x50, fewer IRAM state variables needed
- `func_0x06e4` called for unknown vendor commands (older error path) - `func_0x06e4` called for unknown vendor commands (older error path)
**Likely demodulator**: An I2C-bus demodulator supporting DVB-S/DCII/DSS, with the FX2 as USB bridge. The type codes 3-6 likely correspond to different supported modulation modes or demod silicon revisions. **Likely demodulator**: An I2C-bus demodulator supporting DVB-S/DCII/DSS, with the FX2 as USB bridge. The type codes 3-6 likely correspond to different supported modulation modes or demod silicon revisions.
### FW2 (v2.13.2) -- Second-Generation Parallel-Bus Demodulator ### FW2 (v2.13.2) -- Second-Generation Parallel-Bus Demodulator
**Target**: Revised SkyWalker-1 PCB with a **parallel-bus connected demodulator** (likely a different demod chip or a custom FPGA/ASIC). **Target**: Revised SkyWalker-1 PCB with a **parallel-bus connected demodulator** (likely a different demod chip or a custom FPGA/ASIC).
Evidence: Evidence:
- FUN_CODE_0eea: Parallel bus read using P0 GPIO for control (CS, RD strobe) and P1 for data - FUN_CODE_0eea: Parallel bus read using P0 GPIO for control (CS, RD strobe) and P1 for data
- FUN_CODE_10dd: Copies configuration from external memory (e080-e08e) into demod registers (e6c0-e6cd) -- reads 15 configuration bytes from what appears to be EEPROM/flash config area - FUN_CODE_10dd: Copies configuration from external memory (e080-e08e) into demod registers (e6c0-e6cd) -- reads 15 configuration bytes from what appears to be EEPROM/flash config area
- Reads same device signatures but via parallel bus (P1 ^ 0x1D check, then P1 reads for 0xC5/0xD5/0x5A/0x5B/0x5C) - Reads same device signatures but via parallel bus (P1 ^ 0x1D check, then P1 reads for 0xC5/0xD5/0x5A/0x5B/0x5C)
- P0 = 0xa4 (bit 2 set = specific bus mode select) - P0 = 0xa4 (bit 2 set = specific bus mode select)
- SP = 0x50 - SP = 0x50
- Extra vendor command paths for parallel data direction (P2.1 control in case 0x421/0x423) - Extra vendor command paths for parallel data direction (P2.1 control in case 0x421/0x423)
- Uses FUN_CODE_14e2: Busy-wait on e678 bit 6 (demod ready flag) with 0xFFFF timeout counter - Uses FUN_CODE_14e2: Busy-wait on e678 bit 6 (demod ready flag) with 0xFFFF timeout counter
**Likely demodulator**: A parallel-bus demodulator with 8-bit data port on P1, active-low chip select and read strobe on P0. The external config block (e080-e08e) stores per-unit calibration/tuning data. **Likely demodulator**: A parallel-bus demodulator with 8-bit data port on P1, active-low chip select and read strobe on P0. The external config block (e080-e08e) stores per-unit calibration/tuning data.
### FW3 (v2.13.3) -- Third-Generation with Enhanced Bus Protocol ### FW3 (v2.13.3) -- Third-Generation with Enhanced Bus Protocol
**Target**: Further revised PCB with the **same parallel-bus demodulator as FW2** but with a **different bus interface revision** or a variant chip that requires modified timing. **Target**: Further revised PCB with the **same parallel-bus demodulator as FW2** but with a **different bus interface revision** or a variant chip that requires modified timing.
Evidence: Evidence:
- Same demod configuration loading as FW2 (FUN_CODE_10dd identical) - Same demod configuration loading as FW2 (FUN_CODE_10dd identical)
- Same parallel bus architecture but with dual-phase reading and OR-accumulation - Same parallel bus architecture but with dual-phase reading and OR-accumulation
- P0 = 0xa0 (bit 2 clear = different bus mode or reset polarity) - P0 = 0xa0 (bit 2 clear = different bus mode or reset polarity)
- SP = 0x52 (2 more IRAM bytes: status register moved from 0x4F to 0x51) - SP = 0x52 (2 more IRAM bytes: status register moved from 0x4F to 0x51)
- FUN_CODE_0706 (unique): Multi-mode memory write supporting XDATA, IDATA, and direct addressing -- suggests the demod communicates through multiple address spaces - FUN_CODE_0706 (unique): Multi-mode memory write supporting XDATA, IDATA, and direct addressing -- suggests the demod communicates through multiple address spaces
- The OR-accumulation of P1 reads suggests either: - The OR-accumulation of P1 reads suggests either:
- A demodulator with open-drain outputs requiring multiple read cycles - A demodulator with open-drain outputs requiring multiple read cycles
- Bus settling time issues on the newer PCB layout - Bus settling time issues on the newer PCB layout
- A chip variant that serializes data across multiple bus phases - A chip variant that serializes data across multiple bus phases
--- ---
## 7. Summary Table ## 7. Summary Table
| Aspect | FW1 (v2.13.1) | FW2 (v2.13.2) | FW3 (v2.13.3) | | Aspect | FW1 (v2.13.1) | FW2 (v2.13.2) | FW3 (v2.13.3) |
|--------|---------------|---------------|---------------| |--------|---------------|---------------|---------------|
| **Demod interface** | I2C bus | Parallel bus (P0/P1) | Parallel bus (enhanced) | | **Demod interface** | I2C bus | Parallel bus (P0/P1) | Parallel bus (enhanced) |
| **Bus protocol** | I2C START/STOP/ACK | Single-phase P1 read | Dual-phase P1 read + OR accumulate | | **Bus protocol** | I2C START/STOP/ACK | Single-phase P1 read | Dual-phase P1 read + OR accumulate |
| **Stack pointer** | 0x50 | 0x50 | 0x52 | | **Stack pointer** | 0x50 | 0x50 | 0x52 |
| **P0 init** | 0xa4 | 0xa4 | 0xa0 | | **P0 init** | 0xa4 | 0xa4 | 0xa0 |
| **Status register** | INTMEM 0x4F | INTMEM 0x4F | INTMEM 0x51 | | **Status register** | INTMEM 0x4F | INTMEM 0x4F | INTMEM 0x51 |
| **Config source** | Hardcoded | External (e080-e08e) | External (e080-e08e) | | **Config source** | Hardcoded | External (e080-e08e) | External (e080-e08e) |
| **Demod types supported** | 3-6 (via I2C) | 3-6 (via parallel) | 3-6 (via parallel) | | **Demod types supported** | 3-6 (via I2C) | 3-6 (via parallel) | 3-6 (via parallel) |
| **Binary distance from FW1** | -- | 3,993 bytes | 3,789 bytes | | **Binary distance from FW1** | -- | 3,993 bytes | 3,789 bytes |
| **Binary distance from FW2** | 3,993 bytes | -- | 1,525 bytes | | **Binary distance from FW2** | 3,993 bytes | -- | 1,525 bytes |
## 8. Conclusion ## 8. Conclusion
The three v2.13 firmware sub-variants represent an evolutionary progression of the SkyWalker-1 hardware: The three v2.13 firmware sub-variants represent an evolutionary progression of the SkyWalker-1 hardware:
1. **v2.13.1 (FW1)**: Original design with I2C-connected demodulator. The FX2 communicates with the demod entirely through I2C, using standard master-mode transactions. This is the simplest interface but limited in bandwidth. 1. **v2.13.1 (FW1)**: Original design with I2C-connected demodulator. The FX2 communicates with the demod entirely through I2C, using standard master-mode transactions. This is the simplest interface but limited in bandwidth.
2. **v2.13.2 (FW2)**: Redesigned with a parallel-bus demodulator. The demod data port is connected directly to FX2's P1, with P0 bits used for bus control signals (chip select, read/write strobes). Configuration data is loaded from an external EEPROM area. This provides higher throughput for TS data transfer. 2. **v2.13.2 (FW2)**: Redesigned with a parallel-bus demodulator. The demod data port is connected directly to FX2's P1, with P0 bits used for bus control signals (chip select, read/write strobes). Configuration data is loaded from an external EEPROM area. This provides higher throughput for TS data transfer.
3. **v2.13.3 (FW3)**: Refinement of the FW2 design, likely for a newer demod silicon revision or PCB layout. Uses dual-phase bus reads with signal accumulation, different GPIO defaults, and additional IRAM for state tracking. The OR-accumulation pattern suggests dealing with bus signal integrity improvements. 3. **v2.13.3 (FW3)**: Refinement of the FW2 design, likely for a newer demod silicon revision or PCB layout. Uses dual-phase bus reads with signal accumulation, different GPIO defaults, and additional IRAM for state tracking. The OR-accumulation pattern suggests dealing with bus signal integrity improvements.
The updater program's format string `"FW 2.13.%i"` and its selection logic presumably check the hardware revision (likely via a GPIO strap or I2C ID read) to determine which of the three firmware images to flash. The updater program's format string `"FW 2.13.%i"` and its selection logic presumably check the hardware revision (likely via a GPIO strap or I2C ID read) to determine which of the three firmware images to flash.
All three variants support the same modulation types (DVB-S/QPSK, Turbo QPSK/8PSK, DCII, DSS) -- the demod type codes 3-6 appear in all variants. The differences are purely about the hardware interface, not the feature set. All three variants support the same modulation types (DVB-S/QPSK, Turbo QPSK/8PSK, DCII, DSS) -- the demod type codes 3-6 appear in all variants. The differences are purely about the hardware interface, not the feature set.

View File

@ -1,230 +1,230 @@
; USB Descriptors for Genpix SkyWalker-1 Custom Firmware ; USB Descriptors for Genpix SkyWalker-1 Custom Firmware
; ;
; VID=0x09C0, PID=0x0203 ; VID=0x09C0, PID=0x0203
; Single interface, EP2 IN bulk 512-byte for TS data ; Single interface, EP2 IN bulk 512-byte for TS data
.module DEV_DSCR .module DEV_DSCR
; descriptor types ; descriptor types
DSCR_DEVICE_TYPE=1 DSCR_DEVICE_TYPE=1
DSCR_CONFIG_TYPE=2 DSCR_CONFIG_TYPE=2
DSCR_STRING_TYPE=3 DSCR_STRING_TYPE=3
DSCR_INTERFACE_TYPE=4 DSCR_INTERFACE_TYPE=4
DSCR_ENDPOINT_TYPE=5 DSCR_ENDPOINT_TYPE=5
DSCR_DEVQUAL_TYPE=6 DSCR_DEVQUAL_TYPE=6
; for the repeating interfaces ; for the repeating interfaces
DSCR_INTERFACE_LEN=9 DSCR_INTERFACE_LEN=9
DSCR_ENDPOINT_LEN=7 DSCR_ENDPOINT_LEN=7
; endpoint types ; endpoint types
ENDPOINT_TYPE_CONTROL=0 ENDPOINT_TYPE_CONTROL=0
ENDPOINT_TYPE_ISO=1 ENDPOINT_TYPE_ISO=1
ENDPOINT_TYPE_BULK=2 ENDPOINT_TYPE_BULK=2
ENDPOINT_TYPE_INT=3 ENDPOINT_TYPE_INT=3
.globl _dev_dscr, _dev_qual_dscr, _highspd_dscr, _fullspd_dscr, _dev_strings, _dev_strings_end .globl _dev_dscr, _dev_qual_dscr, _highspd_dscr, _fullspd_dscr, _dev_strings, _dev_strings_end
.area DSCR_AREA (CODE) .area DSCR_AREA (CODE)
_dev_dscr: _dev_dscr:
.db dev_dscr_end-_dev_dscr ; len .db dev_dscr_end-_dev_dscr ; len
.db DSCR_DEVICE_TYPE ; type .db DSCR_DEVICE_TYPE ; type
.dw 0x0002 ; usb 2.0 .dw 0x0002 ; usb 2.0
.db 0xff ; class (vendor specific) .db 0xff ; class (vendor specific)
.db 0xff ; subclass (vendor specific) .db 0xff ; subclass (vendor specific)
.db 0xff ; protocol (vendor specific) .db 0xff ; protocol (vendor specific)
.db 64 ; packet size (ep0) .db 64 ; packet size (ep0)
.dw 0xC009 ; vendor id 0x09C0 (byte-swapped) .dw 0xC009 ; vendor id 0x09C0 (byte-swapped)
.dw 0x0302 ; product id 0x0203 (byte-swapped) .dw 0x0302 ; product id 0x0203 (byte-swapped)
.dw 0x0100 ; version id .dw 0x0100 ; version id
.db 1 ; manufacturer str idx .db 1 ; manufacturer str idx
.db 2 ; product str idx .db 2 ; product str idx
.db 3 ; serial str idx .db 3 ; serial str idx
.db 1 ; n configurations .db 1 ; n configurations
dev_dscr_end: dev_dscr_end:
_dev_qual_dscr: _dev_qual_dscr:
.db dev_qualdscr_end-_dev_qual_dscr .db dev_qualdscr_end-_dev_qual_dscr
.db DSCR_DEVQUAL_TYPE .db DSCR_DEVQUAL_TYPE
.dw 0x0002 ; usb 2.0 .dw 0x0002 ; usb 2.0
.db 0xff .db 0xff
.db 0xff .db 0xff
.db 0xff .db 0xff
.db 64 ; max packet .db 64 ; max packet
.db 1 ; n configs .db 1 ; n configs
.db 0 ; extra reserved byte .db 0 ; extra reserved byte
dev_qualdscr_end: dev_qualdscr_end:
; --- High speed configuration descriptor --- ; --- High speed configuration descriptor ---
_highspd_dscr: _highspd_dscr:
.db highspd_dscr_end-_highspd_dscr .db highspd_dscr_end-_highspd_dscr
.db DSCR_CONFIG_TYPE .db DSCR_CONFIG_TYPE
.db (highspd_dscr_realend-_highspd_dscr) % 256 ; total length lsb .db (highspd_dscr_realend-_highspd_dscr) % 256 ; total length lsb
.db (highspd_dscr_realend-_highspd_dscr) / 256 ; total length msb .db (highspd_dscr_realend-_highspd_dscr) / 256 ; total length msb
.db 1 ; n interfaces .db 1 ; n interfaces
.db 1 ; config number .db 1 ; config number
.db 0 ; config string .db 0 ; config string
.db 0x80 ; attrs = bus powered, no wakeup .db 0x80 ; attrs = bus powered, no wakeup
.db 0xFA ; max power = 500mA (0xFA * 2 = 500) .db 0xFA ; max power = 500mA (0xFA * 2 = 500)
highspd_dscr_end: highspd_dscr_end:
; interface 0 ; interface 0
.db DSCR_INTERFACE_LEN .db DSCR_INTERFACE_LEN
.db DSCR_INTERFACE_TYPE .db DSCR_INTERFACE_TYPE
.db 0 ; index .db 0 ; index
.db 0 ; alt setting idx .db 0 ; alt setting idx
.db 1 ; n endpoints (EP2 IN only) .db 1 ; n endpoints (EP2 IN only)
.db 0xff ; class (vendor specific) .db 0xff ; class (vendor specific)
.db 0xff .db 0xff
.db 0xff .db 0xff
.db 4 ; string index .db 4 ; string index
; endpoint 2 IN (0x82) -- MPEG-2 transport stream bulk ; endpoint 2 IN (0x82) -- MPEG-2 transport stream bulk
.db DSCR_ENDPOINT_LEN .db DSCR_ENDPOINT_LEN
.db DSCR_ENDPOINT_TYPE .db DSCR_ENDPOINT_TYPE
.db 0x82 ; ep2 dir=IN and address .db 0x82 ; ep2 dir=IN and address
.db ENDPOINT_TYPE_BULK ; type .db ENDPOINT_TYPE_BULK ; type
.db 0x00 ; max packet LSB .db 0x00 ; max packet LSB
.db 0x02 ; max packet size=512 bytes .db 0x02 ; max packet size=512 bytes
.db 0x00 ; polling interval .db 0x00 ; polling interval
highspd_dscr_realend: highspd_dscr_realend:
.even .even
; --- Full speed configuration descriptor --- ; --- Full speed configuration descriptor ---
_fullspd_dscr: _fullspd_dscr:
.db fullspd_dscr_end-_fullspd_dscr .db fullspd_dscr_end-_fullspd_dscr
.db DSCR_CONFIG_TYPE .db DSCR_CONFIG_TYPE
.db (fullspd_dscr_realend-_fullspd_dscr) % 256 ; total length lsb .db (fullspd_dscr_realend-_fullspd_dscr) % 256 ; total length lsb
.db (fullspd_dscr_realend-_fullspd_dscr) / 256 ; total length msb .db (fullspd_dscr_realend-_fullspd_dscr) / 256 ; total length msb
.db 1 ; n interfaces .db 1 ; n interfaces
.db 1 ; config number .db 1 ; config number
.db 0 ; config string .db 0 ; config string
.db 0x80 ; attrs = bus powered, no wakeup .db 0x80 ; attrs = bus powered, no wakeup
.db 0xFA ; max power = 500mA .db 0xFA ; max power = 500mA
fullspd_dscr_end: fullspd_dscr_end:
; interface 0 ; interface 0
.db DSCR_INTERFACE_LEN .db DSCR_INTERFACE_LEN
.db DSCR_INTERFACE_TYPE .db DSCR_INTERFACE_TYPE
.db 0 ; index .db 0 ; index
.db 0 ; alt setting idx .db 0 ; alt setting idx
.db 1 ; n endpoints .db 1 ; n endpoints
.db 0xff ; class (vendor specific) .db 0xff ; class (vendor specific)
.db 0xff .db 0xff
.db 0xff .db 0xff
.db 4 ; string index .db 4 ; string index
; endpoint 2 IN (0x82) -- bulk 64 byte at full speed ; endpoint 2 IN (0x82) -- bulk 64 byte at full speed
.db DSCR_ENDPOINT_LEN .db DSCR_ENDPOINT_LEN
.db DSCR_ENDPOINT_TYPE .db DSCR_ENDPOINT_TYPE
.db 0x82 ; ep2 dir=IN and address .db 0x82 ; ep2 dir=IN and address
.db ENDPOINT_TYPE_BULK ; type .db ENDPOINT_TYPE_BULK ; type
.db 0x40 ; max packet LSB = 64 .db 0x40 ; max packet LSB = 64
.db 0x00 ; max packet size MSB .db 0x00 ; max packet size MSB
.db 0x00 ; polling interval .db 0x00 ; polling interval
fullspd_dscr_realend: fullspd_dscr_realend:
.even .even
_dev_strings: _dev_strings:
; string 0 -- language descriptor ; string 0 -- language descriptor
_string0: _string0:
.db string0end-_string0 .db string0end-_string0
.db DSCR_STRING_TYPE .db DSCR_STRING_TYPE
.db 0x09, 0x04 ; English (US) .db 0x09, 0x04 ; English (US)
string0end: string0end:
; string 1 -- manufacturer ; string 1 -- manufacturer
_string1: _string1:
.db string1end-_string1 .db string1end-_string1
.db DSCR_STRING_TYPE .db DSCR_STRING_TYPE
.ascii 'G' .ascii 'G'
.db 0 .db 0
.ascii 'e' .ascii 'e'
.db 0 .db 0
.ascii 'n' .ascii 'n'
.db 0 .db 0
.ascii 'p' .ascii 'p'
.db 0 .db 0
.ascii 'i' .ascii 'i'
.db 0 .db 0
.ascii 'x' .ascii 'x'
.db 0 .db 0
string1end: string1end:
; string 2 -- product ; string 2 -- product
_string2: _string2:
.db string2end-_string2 .db string2end-_string2
.db DSCR_STRING_TYPE .db DSCR_STRING_TYPE
.ascii 'S' .ascii 'S'
.db 0 .db 0
.ascii 'k' .ascii 'k'
.db 0 .db 0
.ascii 'y' .ascii 'y'
.db 0 .db 0
.ascii 'W' .ascii 'W'
.db 0 .db 0
.ascii 'a' .ascii 'a'
.db 0 .db 0
.ascii 'l' .ascii 'l'
.db 0 .db 0
.ascii 'k' .ascii 'k'
.db 0 .db 0
.ascii 'e' .ascii 'e'
.db 0 .db 0
.ascii 'r' .ascii 'r'
.db 0 .db 0
.ascii '-' .ascii '-'
.db 0 .db 0
.ascii '1' .ascii '1'
.db 0 .db 0
.ascii ' ' .ascii ' '
.db 0 .db 0
.ascii 'C' .ascii 'C'
.db 0 .db 0
.ascii 'u' .ascii 'u'
.db 0 .db 0
.ascii 's' .ascii 's'
.db 0 .db 0
.ascii 't' .ascii 't'
.db 0 .db 0
.ascii 'o' .ascii 'o'
.db 0 .db 0
.ascii 'm' .ascii 'm'
.db 0 .db 0
string2end: string2end:
; string 3 -- serial number ; string 3 -- serial number
_string3: _string3:
.db string3end-_string3 .db string3end-_string3
.db DSCR_STRING_TYPE .db DSCR_STRING_TYPE
.ascii '0' .ascii '0'
.db 0 .db 0
.ascii '0' .ascii '0'
.db 0 .db 0
.ascii '0' .ascii '0'
.db 0 .db 0
.ascii '1' .ascii '1'
.db 0 .db 0
string3end: string3end:
; string 4 -- interface ; string 4 -- interface
_string4: _string4:
.db string4end-_string4 .db string4end-_string4
.db DSCR_STRING_TYPE .db DSCR_STRING_TYPE
.ascii 'D' .ascii 'D'
.db 0 .db 0
.ascii 'V' .ascii 'V'
.db 0 .db 0
.ascii 'B' .ascii 'B'
.db 0 .db 0
.ascii '-' .ascii '-'
.db 0 .db 0
.ascii 'S' .ascii 'S'
.db 0 .db 0
string4end: string4end:
_dev_strings_end: _dev_strings_end:
.dw 0x0000 .dw 0x0000

View File

@ -1,280 +1,280 @@
# Genpix SkyWalker-1 DVB-S Linux Kernel Driver Analysis # Genpix SkyWalker-1 DVB-S Linux Kernel Driver Analysis
## Overview ## Overview
The Genpix GP8PSK driver is a Linux kernel DVB-USB compliant driver (found at `drivers/media/usb/dvb-usb/gp8psk.c`) that supports multiple Genpix satellite receiver models. The driver communicates with a Cypress FX2 microcontroller via USB vendor control requests to manage DVB-S satellite reception including demodulation, LNB power control, DiSEqC switching, and signal monitoring. The Genpix GP8PSK driver is a Linux kernel DVB-USB compliant driver (found at `drivers/media/usb/dvb-usb/gp8psk.c`) that supports multiple Genpix satellite receiver models. The driver communicates with a Cypress FX2 microcontroller via USB vendor control requests to manage DVB-S satellite reception including demodulation, LNB power control, DiSEqC switching, and signal monitoring.
--- ---
## 1. VENDOR USB CONTROL COMMANDS (0x80-0x9D) ## 1. VENDOR USB CONTROL COMMANDS (0x80-0x9D)
All vendor commands use USB control transfers with the following pattern: All vendor commands use USB control transfers with the following pattern:
- **USB Type**: `USB_TYPE_VENDOR` (vendor-specific request) - **USB Type**: `USB_TYPE_VENDOR` (vendor-specific request)
- **Direction**: `USB_DIR_IN` (device-to-host) or `USB_DIR_OUT` (host-to-device) - **Direction**: `USB_DIR_IN` (device-to-host) or `USB_DIR_OUT` (host-to-device)
- **Timeout**: 2000ms - **Timeout**: 2000ms
- **Retry Logic**: Up to 3 attempts for IN operations if partial data received - **Retry Logic**: Up to 3 attempts for IN operations if partial data received
- **Data Buffer**: 80 bytes maximum (kernel driver state structure) - **Data Buffer**: 80 bytes maximum (kernel driver state structure)
### Complete Vendor Command Map ### Complete Vendor Command Map
| Cmd | Name | Direction | wValue | wIndex | wLength | Purpose | | Cmd | Name | Direction | wValue | wIndex | wLength | Purpose |
|-----|------|-----------|--------|--------|---------|---------| |-----|------|-----------|--------|--------|---------|---------|
| 0x80 | **GET_8PSK_CONFIG** | IN | 0x0000 | 0x0000 | 1 byte | Read device configuration status byte | | 0x80 | **GET_8PSK_CONFIG** | IN | 0x0000 | 0x0000 | 1 byte | Read device configuration status byte |
| 0x81 | SET_8PSK_CONFIG | OUT | varies | 0x0000 | 0 | Set config (STALL - not implemented) | | 0x81 | SET_8PSK_CONFIG | OUT | varies | 0x0000 | 0 | Set config (STALL - not implemented) |
| 0x82 | (reserved) | -- | -- | -- | -- | STALL - not used | | 0x82 | (reserved) | -- | -- | -- | -- | STALL - not used |
| 0x83 | **I2C_WRITE** | OUT | dev_addr | reg_addr | N bytes | Write to I2C device (BCM4500 demod) | | 0x83 | **I2C_WRITE** | OUT | dev_addr | reg_addr | N bytes | Write to I2C device (BCM4500 demod) |
| 0x84 | **I2C_READ** | IN | dev_addr | reg_addr | N bytes | Read from I2C device (BCM4500 demod) | | 0x84 | **I2C_READ** | IN | dev_addr | reg_addr | N bytes | Read from I2C device (BCM4500 demod) |
| 0x85 | **ARM_TRANSFER** | OUT | onoff (0/1) | 0x0000 | 0 | Start/stop MPEG-2 stream transfer | | 0x85 | **ARM_TRANSFER** | OUT | onoff (0/1) | 0x0000 | 0 | Start/stop MPEG-2 stream transfer |
| 0x86 | **TUNE_8PSK** | OUT | 0x0000 | 0x0000 | 10 bytes | Set tuning parameters | | 0x86 | **TUNE_8PSK** | OUT | 0x0000 | 0x0000 | 10 bytes | Set tuning parameters |
| 0x87 | **GET_SIGNAL_STRENGTH** | IN | 0x0000 | 0x0000 | 6 bytes | Read SNR (signal quality) | | 0x87 | **GET_SIGNAL_STRENGTH** | IN | 0x0000 | 0x0000 | 6 bytes | Read SNR (signal quality) |
| 0x88 | **LOAD_BCM4500** | OUT | 1 (start) | 0x0000 | 0 | Initiate BCM4500 firmware download | | 0x88 | **LOAD_BCM4500** | OUT | 1 (start) | 0x0000 | 0 | Initiate BCM4500 firmware download |
| 0x89 | **BOOT_8PSK** | IN | onoff (0/1) | 0x0000 | 1 byte | Power on/off 8PSK demodulator | | 0x89 | **BOOT_8PSK** | IN | onoff (0/1) | 0x0000 | 1 byte | Power on/off 8PSK demodulator |
| 0x8A | **START_INTERSIL** | IN | onoff (0/1) | 0x0000 | 1 byte | Enable/disable LNB power supply | | 0x8A | **START_INTERSIL** | IN | onoff (0/1) | 0x0000 | 1 byte | Enable/disable LNB power supply |
| 0x8B | **SET_LNB_VOLTAGE** | OUT | voltage (0/1) | 0x0000 | 0 | Set LNB to 13V (0) or 18V (1) | | 0x8B | **SET_LNB_VOLTAGE** | OUT | voltage (0/1) | 0x0000 | 0 | Set LNB to 13V (0) or 18V (1) |
| 0x8C | **SET_22KHZ_TONE** | OUT | onoff (0/1) | 0x0000 | 0 | Enable/disable 22 kHz DiSEqC tone | | 0x8C | **SET_22KHZ_TONE** | OUT | onoff (0/1) | 0x0000 | 0 | Enable/disable 22 kHz DiSEqC tone |
| 0x8D | **SEND_DISEQC_COMMAND** | OUT | msg[0] | 0x0000 | len | Send DiSEqC message to dish switch | | 0x8D | **SEND_DISEQC_COMMAND** | OUT | msg[0] | 0x0000 | len | Send DiSEqC message to dish switch |
| 0x8E | SET_DVB_MODE | OUT | 1 | 0x0000 | 0 | Enable DVB-S mode (STALL on some revisions) | | 0x8E | SET_DVB_MODE | OUT | 1 | 0x0000 | 0 | Enable DVB-S mode (STALL on some revisions) |
| 0x8F | (unknown) | -- | -- | -- | -- | Unknown/internal use | | 0x8F | (unknown) | -- | -- | -- | -- | Unknown/internal use |
| 0x90 | **GET_SIGNAL_LOCK** | IN | 0x0000 | 0x0000 | 1 byte | Read signal lock status bit | | 0x90 | **GET_SIGNAL_LOCK** | IN | 0x0000 | 0x0000 | 1 byte | Read signal lock status bit |
| 0x91-0x98 | (internal use) | -- | -- | -- | -- | I2C/diagnostic reads | | 0x91-0x98 | (internal use) | -- | -- | -- | -- | I2C/diagnostic reads |
| 0x99 | **GET_DEMOD_STATUS** (v2.13+) | IN | 0x0000 | 0x0000 | 1 byte | Read BCM4500 register 0xF9 via I2C | | 0x99 | **GET_DEMOD_STATUS** (v2.13+) | IN | 0x0000 | 0x0000 | 1 byte | Read BCM4500 register 0xF9 via I2C |
| 0x9A | **INIT_DEMOD** (v2.13+) | OUT | 0x0000 | 0x0000 | 0 | Trigger demodulator re-init (up to 3 attempts) | | 0x9A | **INIT_DEMOD** (v2.13+) | OUT | 0x0000 | 0x0000 | 0 | Trigger demodulator re-init (up to 3 attempts) |
| 0x9B | (reserved) | -- | -- | -- | -- | STALL - not used | | 0x9B | (reserved) | -- | -- | -- | -- | STALL - not used |
| 0x9C | **DELAY_COMMAND** (v2.13+) | OUT | delay_param | 0x0000 | 0 | Perform tuning/acquisition delay with polling | | 0x9C | **DELAY_COMMAND** (v2.13+) | OUT | delay_param | 0x0000 | 0 | Perform tuning/acquisition delay with polling |
| 0x9D | **CW3K_INIT** | OUT | onoff (0/1) | 0x0000 | 0 | Initialize SkyWalker CW3K model | | 0x9D | **CW3K_INIT** | OUT | onoff (0/1) | 0x0000 | 0 | Initialize SkyWalker CW3K model |
### Configuration Status Byte (GET_8PSK_CONFIG - 0x80) ### Configuration Status Byte (GET_8PSK_CONFIG - 0x80)
The returned byte is a bit-mapped status register: The returned byte is a bit-mapped status register:
``` ```
Bit 0 (0x01): bm8pskStarted - Device booted and running Bit 0 (0x01): bm8pskStarted - Device booted and running
Bit 1 (0x02): bm8pskFW_Loaded - BCM4500 firmware loaded Bit 1 (0x02): bm8pskFW_Loaded - BCM4500 firmware loaded
Bit 2 (0x04): bmIntersilOn - LNB power supply enabled Bit 2 (0x04): bmIntersilOn - LNB power supply enabled
Bit 3 (0x08): bmDVBmode - DVB mode enabled Bit 3 (0x08): bmDVBmode - DVB mode enabled
Bit 4 (0x10): bm22kHz - 22 kHz tone active Bit 4 (0x10): bm22kHz - 22 kHz tone active
Bit 5 (0x20): bmSEL18V - 18V LNB voltage selected (else 13V) Bit 5 (0x20): bmSEL18V - 18V LNB voltage selected (else 13V)
Bit 6 (0x40): bmDCtuned - DC offset tuning complete Bit 6 (0x40): bmDCtuned - DC offset tuning complete
Bit 7 (0x80): bmArmed - MPEG-2 stream transfer armed Bit 7 (0x80): bmArmed - MPEG-2 stream transfer armed
``` ```
--- ---
## 2. FIRMWARE LOADING SEQUENCE ## 2. FIRMWARE LOADING SEQUENCE
### Two-Stage Firmware Loading ### Two-Stage Firmware Loading
The device requires **two separate firmware files**: The device requires **two separate firmware files**:
#### Stage 1: FX2 RAM Code (Bootloader Phase) #### Stage 1: FX2 RAM Code (Bootloader Phase)
- **File**: `dvb-usb-gp8psk-01.fw` - **File**: `dvb-usb-gp8psk-01.fw`
- **Purpose**: Cypress FX2 microcontroller firmware - **Purpose**: Cypress FX2 microcontroller firmware
- **When**: Loaded automatically by DVB-USB framework during device enumeration (cold-to-warm boot transition) - **When**: Loaded automatically by DVB-USB framework during device enumeration (cold-to-warm boot transition)
- **How**: Standard USB firmware upload via control endpoint (0xA0 vendor request to CPUCS) - **How**: Standard USB firmware upload via control endpoint (0xA0 vendor request to CPUCS)
- **Device Mode**: Cold boot (VID 0x09C0, PID 0x0200) - **Device Mode**: Cold boot (VID 0x09C0, PID 0x0200)
#### Stage 2: BCM4500 Demodulator Firmware (Tuner Phase) #### Stage 2: BCM4500 Demodulator Firmware (Tuner Phase)
- **File**: `dvb-usb-gp8psk-02.fw` - **File**: `dvb-usb-gp8psk-02.fw`
- **Purpose**: Broadcom BCM4500 DVB-S demodulator chip firmware - **Purpose**: Broadcom BCM4500 DVB-S demodulator chip firmware
- **When**: Loaded after device power-on via LOAD_BCM4500 command - **When**: Loaded after device power-on via LOAD_BCM4500 command
- **How**: Custom binary protocol via USB control transfers - **How**: Custom binary protocol via USB control transfers
- **Conditions**: Only for Rev.1 Warm devices; Rev.2 and SkyWalker have firmware burned in ROM - **Conditions**: Only for Rev.1 Warm devices; Rev.2 and SkyWalker have firmware burned in ROM
### BCM4500 Firmware Loading Protocol ### BCM4500 Firmware Loading Protocol
```c ```c
// Step 1: Initiate load // Step 1: Initiate load
gp8psk_usb_out_op(device, LOAD_BCM4500, 1, 0, NULL, 0); // 0x88 cmd, wValue=1 gp8psk_usb_out_op(device, LOAD_BCM4500, 1, 0, NULL, 0); // 0x88 cmd, wValue=1
// Step 2: Download firmware chunks // Step 2: Download firmware chunks
// Format: [chunk_length] [data...] repeated, terminated by 0xFF // Format: [chunk_length] [data...] repeated, terminated by 0xFF
ptr = fw_data; ptr = fw_data;
while (ptr[0] != 0xFF) { while (ptr[0] != 0xFF) {
chunk_size = ptr[0] + 4; // length byte + 3 extra bytes chunk_size = ptr[0] + 4; // length byte + 3 extra bytes
if (chunk_size > 64) ERROR("chunk too large"); if (chunk_size > 64) ERROR("chunk too large");
buf = copy chunk_size bytes from ptr; buf = copy chunk_size bytes from ptr;
usb_control_msg(device, USB_SNDCTRLPIPE, 0, ..., buf, chunk_size, 2000ms); usb_control_msg(device, USB_SNDCTRLPIPE, 0, ..., buf, chunk_size, 2000ms);
ptr += chunk_size; ptr += chunk_size;
} }
``` ```
### Boot Sequence Flow (Power-On) ### Boot Sequence Flow (Power-On)
``` ```
1. Read device config (GET_8PSK_CONFIG - 0x80) 1. Read device config (GET_8PSK_CONFIG - 0x80)
+-- Check bit 0: Device started? +-- Check bit 0: Device started?
2. If not started: 2. If not started:
+-- Boot device (BOOT_8PSK - 0x89, wValue=1) +-- Boot device (BOOT_8PSK - 0x89, wValue=1)
+-- Get firmware version (via 0x0B: FW_VERSION_READ) +-- Get firmware version (via 0x0B: FW_VERSION_READ)
3. If firmware not loaded (check bit 1): 3. If firmware not loaded (check bit 1):
+-- Load BCM4500 firmware (LOAD_BCM4500 - 0x88) +-- Load BCM4500 firmware (LOAD_BCM4500 - 0x88)
4. If LNB not powered (check bit 2): 4. If LNB not powered (check bit 2):
+-- Enable LNB supply (START_INTERSIL - 0x8A, wValue=1) +-- Enable LNB supply (START_INTERSIL - 0x8A, wValue=1)
5. Set DVB mode (on some revisions): 5. Set DVB mode (on some revisions):
+-- SET_DVB_MODE - 0x8E, wValue=1 +-- SET_DVB_MODE - 0x8E, wValue=1
6. Abort any pending MPEG transfer: 6. Abort any pending MPEG transfer:
+-- ARM_TRANSFER - 0x85, wValue=0 (cancel) +-- ARM_TRANSFER - 0x85, wValue=0 (cancel)
7. Ready for tuning/reception 7. Ready for tuning/reception
``` ```
--- ---
## 3. TUNING AND DEMODULATION FLOW ## 3. TUNING AND DEMODULATION FLOW
### Frequency Tuning (TUNE_8PSK - 0x86) ### Frequency Tuning (TUNE_8PSK - 0x86)
The tuning command transmits a 10-byte parameter structure: The tuning command transmits a 10-byte parameter structure:
``` ```
Bytes 0-3: Symbol Rate (Little-Endian 32-bit, in sps) Bytes 0-3: Symbol Rate (Little-Endian 32-bit, in sps)
Bytes 4-7: Tuner Frequency (Little-Endian 32-bit, in kHz) Bytes 4-7: Tuner Frequency (Little-Endian 32-bit, in kHz)
Byte 8: Modulation Type (see table below) Byte 8: Modulation Type (see table below)
Byte 9: Inner FEC Rate / reserved Byte 9: Inner FEC Rate / reserved
``` ```
### Modulation Types ### Modulation Types
``` ```
ADV_MOD_DVB_QPSK = 0 // DVB-S standard QPSK ADV_MOD_DVB_QPSK = 0 // DVB-S standard QPSK
ADV_MOD_TURBO_QPSK = 1 // Turbo QPSK ADV_MOD_TURBO_QPSK = 1 // Turbo QPSK
ADV_MOD_TURBO_8PSK = 2 // Turbo 8PSK (Trellis) ADV_MOD_TURBO_8PSK = 2 // Turbo 8PSK (Trellis)
ADV_MOD_TURBO_16QAM = 3 // Turbo 16QAM ADV_MOD_TURBO_16QAM = 3 // Turbo 16QAM
ADV_MOD_DCII_C_QPSK = 4 // Digicipher II Combo ADV_MOD_DCII_C_QPSK = 4 // Digicipher II Combo
ADV_MOD_DCII_I_QPSK = 5 // Digicipher II I-stream (split) ADV_MOD_DCII_I_QPSK = 5 // Digicipher II I-stream (split)
ADV_MOD_DCII_Q_QPSK = 6 // Digicipher II Q-stream (split) ADV_MOD_DCII_Q_QPSK = 6 // Digicipher II Q-stream (split)
ADV_MOD_DCII_C_OQPSK = 7 // Digicipher II offset QPSK ADV_MOD_DCII_C_OQPSK = 7 // Digicipher II offset QPSK
ADV_MOD_DSS_QPSK = 8 // DSS/DIRECTV QPSK ADV_MOD_DSS_QPSK = 8 // DSS/DIRECTV QPSK
ADV_MOD_DVB_BPSK = 9 // DVB-S BPSK ADV_MOD_DVB_BPSK = 9 // DVB-S BPSK
``` ```
### Complete Tuning Sequence ### Complete Tuning Sequence
``` ```
1. Configure LNB voltage based on polarization: 1. Configure LNB voltage based on polarization:
H/CIRCULAR_L -> 18V (SET_LNB_VOLTAGE - 0x8B, wValue=1) H/CIRCULAR_L -> 18V (SET_LNB_VOLTAGE - 0x8B, wValue=1)
V/CIRCULAR_R -> 13V (SET_LNB_VOLTAGE - 0x8B, wValue=0) V/CIRCULAR_R -> 13V (SET_LNB_VOLTAGE - 0x8B, wValue=0)
2. Set 22 kHz tone: 2. Set 22 kHz tone:
SET_22KHZ_TONE - 0x8C, wValue=0/1 SET_22KHZ_TONE - 0x8C, wValue=0/1
3. Send DiSEqC switch command if needed (see section 4) 3. Send DiSEqC switch command if needed (see section 4)
4. Send tuning command: 4. Send tuning command:
TUNE_8PSK - 0x86, 10-byte parameter buffer TUNE_8PSK - 0x86, 10-byte parameter buffer
5. Poll for lock: 5. Poll for lock:
GET_SIGNAL_LOCK - 0x90 (returns 1 byte, non-zero = locked) GET_SIGNAL_LOCK - 0x90 (returns 1 byte, non-zero = locked)
``` ```
### Signal Quality Monitoring ### Signal Quality Monitoring
**GET_SIGNAL_STRENGTH (0x87)** returns 6-byte buffer: **GET_SIGNAL_STRENGTH (0x87)** returns 6-byte buffer:
``` ```
Bytes 0-1: SNR value (LE 16-bit, dBu*256 units) Bytes 0-1: SNR value (LE 16-bit, dBu*256 units)
Bytes 2-5: Reserved/diagnostics Bytes 2-5: Reserved/diagnostics
``` ```
SNR scaling: `snr * 17` maps to 0-65535 (100% at SNR >= 0x0F00) SNR scaling: `snr * 17` maps to 0-65535 (100% at SNR >= 0x0F00)
--- ---
## 4. DiSEqC COMMAND HANDLING (0x8D) ## 4. DiSEqC COMMAND HANDLING (0x8D)
### Tone Burst (Mini DiSEqC) ### Tone Burst (Mini DiSEqC)
```c ```c
// For legacy 2-way switches // For legacy 2-way switches
gp8psk_usb_out_op(device, SEND_DISEQC_COMMAND, gp8psk_usb_out_op(device, SEND_DISEQC_COMMAND,
burst_value, // SEC_MINI_A=0x00 or SEC_MINI_B=0x01 burst_value, // SEC_MINI_A=0x00 or SEC_MINI_B=0x01
0, NULL, 0); 0, NULL, 0);
``` ```
### Full DiSEqC Message (3-6 bytes) ### Full DiSEqC Message (3-6 bytes)
```c ```c
// Standard DiSEqC 1.0/1.1/1.2 messages // Standard DiSEqC 1.0/1.1/1.2 messages
gp8psk_usb_out_op(device, SEND_DISEQC_COMMAND, gp8psk_usb_out_op(device, SEND_DISEQC_COMMAND,
msg[0], // Framing byte as wValue msg[0], // Framing byte as wValue
0, 0,
msg, // Full message buffer msg, // Full message buffer
msg_len); // 3-6 bytes msg_len); // 3-6 bytes
``` ```
Common framing bytes: 0xE0 (broadcast, no reply), 0xE1 (addressed, no reply) Common framing bytes: 0xE0 (broadcast, no reply), 0xE1 (addressed, no reply)
--- ---
## 5. DEVICE TABLE AND USB IDS ## 5. DEVICE TABLE AND USB IDS
### Kernel Module Aliases (Linux 6.16.5) ### Kernel Module Aliases (Linux 6.16.5)
``` ```
usb:v09C0p0200 - Rev.1 Cold boot (requires FX2 firmware upload) usb:v09C0p0200 - Rev.1 Cold boot (requires FX2 firmware upload)
usb:v09C0p0201 - Rev.1 Warm (requires BCM4500 FW via 0x88) usb:v09C0p0201 - Rev.1 Warm (requires BCM4500 FW via 0x88)
usb:v09C0p0202 - Rev.2 (BCM4500 in ROM) usb:v09C0p0202 - Rev.2 (BCM4500 in ROM)
usb:v09C0p0203 - SkyWalker-1 (PID confirmed on actual hardware) usb:v09C0p0203 - SkyWalker-1 (PID confirmed on actual hardware)
usb:v09C0p0204 - SkyWalker-1 (alternate revision) usb:v09C0p0204 - SkyWalker-1 (alternate revision)
usb:v09C0p0206 - SkyWalker CW3K (requires CW3K_INIT 0x9D) usb:v09C0p0206 - SkyWalker CW3K (requires CW3K_INIT 0x9D)
``` ```
Note: PID 0x0205 (SkyWalker-2) is absent from the 6.16.5 kernel build. Note: PID 0x0205 (SkyWalker-2) is absent from the 6.16.5 kernel build.
Note: PID 0x0203 was not in earlier kernel versions (e.g., v6.6.1). Note: PID 0x0203 was not in earlier kernel versions (e.g., v6.6.1).
### Device Properties ### Device Properties
```c ```c
gp8psk_properties { gp8psk_properties {
usb_ctrl = CYPRESS_FX2; usb_ctrl = CYPRESS_FX2;
firmware = "dvb-usb-gp8psk-01.fw"; firmware = "dvb-usb-gp8psk-01.fw";
num_adapters = 1; num_adapters = 1;
endpoint = 0x82 (IN bulk); endpoint = 0x82 (IN bulk);
stream = USB_BULK; stream = USB_BULK;
count = 7 URBs; count = 7 URBs;
buffersize = 8192 bytes per URB; buffersize = 8192 bytes per URB;
generic_bulk_ctrl_endpoint = 0x01; generic_bulk_ctrl_endpoint = 0x01;
} }
``` ```
--- ---
## 6. CORRELATION: KERNEL DRIVER vs FIRMWARE ANALYSIS ## 6. CORRELATION: KERNEL DRIVER vs FIRMWARE ANALYSIS
### Commands Used by Kernel Driver ### Commands Used by Kernel Driver
| Command | Driver Uses | v2.06 FW | v2.13 FW | Rev.2 FW | | Command | Driver Uses | v2.06 FW | v2.13 FW | Rev.2 FW |
|---------|-------------|----------|----------|----------| |---------|-------------|----------|----------|----------|
| 0x80 GET_8PSK_CONFIG | Boot check | OK | OK | OK | | 0x80 GET_8PSK_CONFIG | Boot check | OK | OK | OK |
| 0x83 I2C_WRITE | BCM4500 reg writes | OK | OK | OK | | 0x83 I2C_WRITE | BCM4500 reg writes | OK | OK | OK |
| 0x84 I2C_READ | BCM4500 reg reads | OK | OK | OK | | 0x84 I2C_READ | BCM4500 reg reads | OK | OK | OK |
| 0x85 ARM_TRANSFER | Stream start/stop | OK | OK | OK | | 0x85 ARM_TRANSFER | Stream start/stop | OK | OK | OK |
| 0x86 TUNE_8PSK | Frequency tuning | OK | OK | OK | | 0x86 TUNE_8PSK | Frequency tuning | OK | OK | OK |
| 0x87 GET_SIGNAL_STRENGTH | SNR readback | OK | Changed | OK | | 0x87 GET_SIGNAL_STRENGTH | SNR readback | OK | Changed | OK |
| 0x88 LOAD_BCM4500 | BCM4500 FW load | **STALL** | **STALL** | **STALL** | | 0x88 LOAD_BCM4500 | BCM4500 FW load | **STALL** | **STALL** | **STALL** |
| 0x89 BOOT_8PSK | Power on/off | OK | OK | OK | | 0x89 BOOT_8PSK | Power on/off | OK | OK | OK |
| 0x8A START_INTERSIL | LNB power | OK | OK | OK | | 0x8A START_INTERSIL | LNB power | OK | OK | OK |
| 0x8B SET_LNB_VOLTAGE | 13V/18V | OK | OK | OK | | 0x8B SET_LNB_VOLTAGE | 13V/18V | OK | OK | OK |
| 0x8C SET_22KHZ_TONE | Tone control | OK | OK | OK | | 0x8C SET_22KHZ_TONE | Tone control | OK | OK | OK |
| 0x8D SEND_DISEQC | DiSEqC messages | OK (GPIO) | OK (I2C) | OK | | 0x8D SEND_DISEQC | DiSEqC messages | OK (GPIO) | OK (I2C) | OK |
| 0x90 GET_SIGNAL_LOCK | Lock status | OK | OK | OK | | 0x90 GET_SIGNAL_LOCK | Lock status | OK | OK | OK |
| 0x9D CW3K_INIT | CW3K only | N/A | v2.13 only | N/A | | 0x9D CW3K_INIT | CW3K only | N/A | v2.13 only | N/A |
### Key Finding: LOAD_BCM4500 (0x88) STALLs ### Key Finding: LOAD_BCM4500 (0x88) STALLs
Command 0x88 routes to the STALL handler in all extracted firmware versions. Command 0x88 routes to the STALL handler in all extracted firmware versions.
The kernel driver only sends this command for Rev.1 Warm (PID 0x0201) devices, The kernel driver only sends this command for Rev.1 Warm (PID 0x0201) devices,
after checking that `bm8pskFW_Loaded` (bit 1) is NOT set. On Rev.2/SkyWalker after checking that `bm8pskFW_Loaded` (bit 1) is NOT set. On Rev.2/SkyWalker
hardware, this bit is already set at boot (BCM4500 firmware in ROM), so the hardware, this bit is already set at boot (BCM4500 firmware in ROM), so the
driver never attempts the load. The STALL is a safety net. driver never attempts the load. The STALL is a safety net.
--- ---
## Sources ## Sources
- Linux kernel 6.16.5 `dvb-usb-gp8psk` module (installed on analysis system) - Linux kernel 6.16.5 `dvb-usb-gp8psk` module (installed on analysis system)
- Linux kernel source: `drivers/media/usb/dvb-usb/gp8psk.c`, `gp8psk.h`, `gp8psk-fe.c` - Linux kernel source: `drivers/media/usb/dvb-usb/gp8psk.c`, `gp8psk.h`, `gp8psk-fe.c`
- Windows BDA driver source: `SkyWalker1_Final_Release/Include/SkyWalker1Control.h` - Windows BDA driver source: `SkyWalker1_Final_Release/Include/SkyWalker1Control.h`
- Firmware reverse engineering via Ghidra (ports 8193-8197) - Firmware reverse engineering via Ghidra (ports 8193-8197)

File diff suppressed because it is too large Load Diff

View File

@ -1,425 +1,425 @@
# Genpix GP8PSK Kernel Firmware File Analysis # Genpix GP8PSK Kernel Firmware File Analysis
## 1. Firmware File Search Results ## 1. Firmware File Search Results
### Standard Locations Checked ### Standard Locations Checked
| Path | Result | | Path | Result |
|------|--------| |------|--------|
| `/lib/firmware/dvb-usb-gp8psk-01.fw` | **Not found** | | `/lib/firmware/dvb-usb-gp8psk-01.fw` | **Not found** |
| `/lib/firmware/dvb-usb-gp8psk-02.fw` | **Not found** | | `/lib/firmware/dvb-usb-gp8psk-02.fw` | **Not found** |
| `/usr/lib/firmware/dvb-usb-gp8psk-01.fw` | **Not found** | | `/usr/lib/firmware/dvb-usb-gp8psk-01.fw` | **Not found** |
| `/usr/lib/firmware/dvb-usb-gp8psk-02.fw` | **Not found** | | `/usr/lib/firmware/dvb-usb-gp8psk-02.fw` | **Not found** |
| `/usr/share/firmware/` | Directory does not exist | | `/usr/share/firmware/` | Directory does not exist |
### Package Search ### Package Search
- `linux-firmware` (v20260110-1) is installed but contains **no gp8psk files** - `linux-firmware` (v20260110-1) is installed but contains **no gp8psk files**
- The `/usr/lib/firmware/WHENCE` manifest has **no gp8psk entry** - The `/usr/lib/firmware/WHENCE` manifest has **no gp8psk entry**
- `pacman -F dvb-usb-gp8psk-01.fw` returns no results -- no Arch package provides it - `pacman -F dvb-usb-gp8psk-01.fw` returns no results -- no Arch package provides it
- `pacman -Ss gp8psk` finds nothing - `pacman -Ss gp8psk` finds nothing
### linux-firmware Git Repository ### linux-firmware Git Repository
The upstream linux-firmware repository at `git.kernel.org` was checked. The gp8psk firmware files have **never been included** in the linux-firmware collection. Other DVB-USB firmware files exist (dib0700, it9135, terratec-h5-drxk), but gp8psk is absent. The upstream linux-firmware repository at `git.kernel.org` was checked. The gp8psk firmware files have **never been included** in the linux-firmware collection. Other DVB-USB firmware files exist (dib0700, it9135, terratec-h5-drxk), but gp8psk is absent.
### Kernel get_dvb_firmware Script ### Kernel get_dvb_firmware Script
The kernel's `scripts/get_dvb_firmware` helper (which downloads firmware from various vendor sites) has **no entry for gp8psk**. The original firmware was presumably distributed by Genpix Electronics directly, likely packaged with their Windows BDA driver installer. The kernel's `scripts/get_dvb_firmware` helper (which downloads firmware from various vendor sites) has **no entry for gp8psk**. The original firmware was presumably distributed by Genpix Electronics directly, likely packaged with their Windows BDA driver installer.
### Filesystem-Wide Search ### Filesystem-Wide Search
A full filesystem search (`find / -name 'dvb-usb-gp8psk*'`) found only the compiled kernel module (`.ko.zst`), no `.fw` firmware files anywhere on the system. A full filesystem search (`find / -name 'dvb-usb-gp8psk*'`) found only the compiled kernel module (`.ko.zst`), no `.fw` firmware files anywhere on the system.
### Conclusion ### Conclusion
**Neither `dvb-usb-gp8psk-01.fw` nor `dvb-usb-gp8psk-02.fw` exist on this system or in any standard distribution channel.** The gp8psk firmware was never open-sourced or contributed to linux-firmware. **Neither `dvb-usb-gp8psk-01.fw` nor `dvb-usb-gp8psk-02.fw` exist on this system or in any standard distribution channel.** The gp8psk firmware was never open-sourced or contributed to linux-firmware.
--- ---
## 2. Why SkyWalker-1 Works Without FW01/FW02 ## 2. Why SkyWalker-1 Works Without FW01/FW02
### The Driver Device Table Tells the Story ### The Driver Device Table Tells the Story
From `gp8psk.c` (kernel source): From `gp8psk.c` (kernel source):
```c ```c
static struct dvb_usb_device_properties gp8psk_properties = { static struct dvb_usb_device_properties gp8psk_properties = {
.usb_ctrl = CYPRESS_FX2, .usb_ctrl = CYPRESS_FX2,
.firmware = "dvb-usb-gp8psk-01.fw", .firmware = "dvb-usb-gp8psk-01.fw",
// ... // ...
.devices = { .devices = {
{ .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver", { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
.cold_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_COLD], NULL }, // <-- HAS cold_ids .cold_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_COLD], NULL }, // <-- HAS cold_ids
.warm_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_WARM], NULL }, .warm_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_WARM], NULL },
}, },
{ .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver", { .name = "Genpix 8PSK-to-USB2 Rev.2 DVB-S receiver",
.cold_ids = { NULL }, // <-- NO cold_ids .cold_ids = { NULL }, // <-- NO cold_ids
.warm_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_2], NULL }, .warm_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_2], NULL },
}, },
{ .name = "Genpix SkyWalker-1 DVB-S receiver", { .name = "Genpix SkyWalker-1 DVB-S receiver",
.cold_ids = { NULL }, // <-- NO cold_ids .cold_ids = { NULL }, // <-- NO cold_ids
.warm_ids = { &gp8psk_usb_table[GENPIX_SKYWALKER_1], NULL }, .warm_ids = { &gp8psk_usb_table[GENPIX_SKYWALKER_1], NULL },
}, },
// ... // ...
} }
}; };
``` ```
**Only Rev.1 Cold (PID 0x0200) triggers firmware download.** When `cold_ids` is NULL, the DVB-USB framework skips the firmware loading step entirely. The device is assumed to already be in "warm" state. **Only Rev.1 Cold (PID 0x0200) triggers firmware download.** When `cold_ids` is NULL, the DVB-USB framework skips the firmware loading step entirely. The device is assumed to already be in "warm" state.
### FW01 Loading Path ### FW01 Loading Path
``` ```
USB device enumeration USB device enumeration
| |
+-- DVB-USB framework matches USB IDs +-- DVB-USB framework matches USB IDs
+-- Checks cold_ids vs warm_ids +-- Checks cold_ids vs warm_ids
| | | |
| +-- cold_ids match? -> dvb_usb_download_firmware() | +-- cold_ids match? -> dvb_usb_download_firmware()
| | | -> request_firmware("dvb-usb-gp8psk-01.fw") | | | -> request_firmware("dvb-usb-gp8psk-01.fw")
| | | -> usb_cypress_load_firmware() [hexline parser] | | | -> usb_cypress_load_firmware() [hexline parser]
| | | -> Device re-enumerates with warm PID | | | -> Device re-enumerates with warm PID
| | | | | |
| +-- warm_ids match? -> Skip firmware, proceed to frontend attach | +-- warm_ids match? -> Skip firmware, proceed to frontend attach
| |
+-- SkyWalker-1 (PID 0x0203) -> warm_ids only -> NO FW01 NEEDED +-- SkyWalker-1 (PID 0x0203) -> warm_ids only -> NO FW01 NEEDED
``` ```
### FW02 Loading Path ### FW02 Loading Path
From `gp8psk_power_ctrl()`: From `gp8psk_power_ctrl()`:
```c ```c
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) // Only for Rev.1! if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) // Only for Rev.1!
if (!(status & bm8pskFW_Loaded)) if (!(status & bm8pskFW_Loaded))
if (gp8psk_load_bcm4500fw(d)) if (gp8psk_load_bcm4500fw(d))
return -EINVAL; return -EINVAL;
``` ```
BCM4500 firmware loading (`dvb-usb-gp8psk-02.fw`) is **only attempted for Rev.1 Warm devices** (PID 0x0201). Rev.2 and SkyWalker devices have the BCM4500 firmware burned into ROM, so `bm8pskFW_Loaded` (bit 1 of `GET_8PSK_CONFIG`) is already set at boot. BCM4500 firmware loading (`dvb-usb-gp8psk-02.fw`) is **only attempted for Rev.1 Warm devices** (PID 0x0201). Rev.2 and SkyWalker devices have the BCM4500 firmware burned into ROM, so `bm8pskFW_Loaded` (bit 1 of `GET_8PSK_CONFIG`) is already set at boot.
### Summary ### Summary
| Device | PID | Needs FW01? | Needs FW02? | Boot Source | | Device | PID | Needs FW01? | Needs FW02? | Boot Source |
|--------|-----|-------------|-------------|-------------| |--------|-----|-------------|-------------|-------------|
| Rev.1 Cold | 0x0200 | **YES** | -- | RAM (empty) | | Rev.1 Cold | 0x0200 | **YES** | -- | RAM (empty) |
| Rev.1 Warm | 0x0201 | No | **YES** | RAM (FW01 loaded) | | Rev.1 Warm | 0x0201 | No | **YES** | RAM (FW01 loaded) |
| Rev.2 | 0x0202 | No | No | EEPROM | | Rev.2 | 0x0202 | No | No | EEPROM |
| SkyWalker-1 | 0x0203 | No | No | EEPROM | | SkyWalker-1 | 0x0203 | No | No | EEPROM |
| SkyWalker-2 | 0x0205 | No | No | EEPROM | | SkyWalker-2 | 0x0205 | No | No | EEPROM |
| SkyWalker CW3K | 0x0206 | No | No | EEPROM | | SkyWalker CW3K | 0x0206 | No | No | EEPROM |
**The SkyWalker-1 boots entirely from its onboard EEPROM. It never requests either firmware file from the host.** **The SkyWalker-1 boots entirely from its onboard EEPROM. It never requests either firmware file from the host.**
--- ---
## 3. FW01 Expected Format: DVB-USB Binary Hexline ## 3. FW01 Expected Format: DVB-USB Binary Hexline
### Format Specification ### Format Specification
The DVB-USB framework's `dvb_usb_get_hexline()` parser reads a **compact binary representation** of Intel HEX records. This is NOT standard Intel HEX text (`:10000000...`), nor the kernel's `ihex_binrec` format from `<linux/ihex.h>`. The DVB-USB framework's `dvb_usb_get_hexline()` parser reads a **compact binary representation** of Intel HEX records. This is NOT standard Intel HEX text (`:10000000...`), nor the kernel's `ihex_binrec` format from `<linux/ihex.h>`.
**Record structure:** **Record structure:**
``` ```
Offset Size Field Offset Size Field
------ ---- ----- ------ ---- -----
0 1 len - Number of data bytes in this record 0 1 len - Number of data bytes in this record
1 1 addr_lo - Target address, low byte 1 1 addr_lo - Target address, low byte
2 1 addr_hi - Target address, high byte 2 1 addr_hi - Target address, high byte
3 1 type - Record type (0x00=data, 0x01=EOF, 0x04=extended addr) 3 1 type - Record type (0x00=data, 0x01=EOF, 0x04=extended addr)
4 len data[] - Payload bytes 4 len data[] - Payload bytes
4+len 1 chk - Checksum byte 4+len 1 chk - Checksum byte
``` ```
Total bytes per record: `len + 5` Total bytes per record: `len + 5`
The parser advances position by `len + 5` each iteration. Type 0x04 records carry extended linear address bits in `data[0]` and `data[1]`, allowing 32-bit addressing. The parser advances position by `len + 5` each iteration. Type 0x04 records carry extended linear address bits in `data[0]` and `data[1]`, allowing 32-bit addressing.
### Loading Mechanism ### Loading Mechanism
`usb_cypress_load_firmware()` performs: `usb_cypress_load_firmware()` performs:
1. Halt FX2 CPU: write `0x01` to CPUCS register (0xE600) 1. Halt FX2 CPU: write `0x01` to CPUCS register (0xE600)
2. For each hexline record: write `data[0..len-1]` to FX2 RAM at `addr` via 0xA0 vendor request 2. For each hexline record: write `data[0..len-1]` to FX2 RAM at `addr` via 0xA0 vendor request
3. Restart FX2 CPU: write `0x00` to CPUCS register (0xE600) 3. Restart FX2 CPU: write `0x00` to CPUCS register (0xE600)
The 0xA0 vendor request is handled by the FX2's built-in boot ROM, which writes directly to program/data RAM regardless of whether user firmware is running. The 0xA0 vendor request is handled by the FX2's built-in boot ROM, which writes directly to program/data RAM regardless of whether user firmware is running.
### Comparison with Other DVB-USB Firmware Files ### Comparison with Other DVB-USB Firmware Files
Other firmware files installed on this system confirm the format: Other firmware files installed on this system confirm the format:
| File | Size | First Record | | File | Size | First Record |
|------|------|-------------| |------|------|-------------|
| `dvb-usb-dib0700-1.20.fw` | 33,768 bytes | len=2, addr=0x0000, type=0x04 (ext addr) | | `dvb-usb-dib0700-1.20.fw` | 33,768 bytes | len=2, addr=0x0000, type=0x04 (ext addr) |
| `dvb-usb-it9135-01.fw` | 8,128 bytes | len=3, addr=0x0000, type=0x03 | | `dvb-usb-it9135-01.fw` | 8,128 bytes | len=3, addr=0x0000, type=0x03 |
| `dvb-usb-it9135-02.fw` | 5,834 bytes | len=3, addr=0x0000, type=0x03 | | `dvb-usb-it9135-02.fw` | 5,834 bytes | len=3, addr=0x0000, type=0x03 |
--- ---
## 4. Our Extracted Firmware Format: Cypress C2 EEPROM Boot ## 4. Our Extracted Firmware Format: Cypress C2 EEPROM Boot
### C2 Header Structure ### C2 Header Structure
All extracted firmware dumps are in **Cypress C2 IIC second-stage boot format**, as stored in the device's EEPROM. This format is read by the FX2's internal boot ROM on power-up. All extracted firmware dumps are in **Cypress C2 IIC second-stage boot format**, as stored in the device's EEPROM. This format is read by the FX2's internal boot ROM on power-up.
**C2 header (8 bytes):** **C2 header (8 bytes):**
``` ```
Offset Size Field Offset Size Field
------ ---- ----- ------ ---- -----
0 1 marker - Always 0xC2 (indicates external memory, large code model) 0 1 marker - Always 0xC2 (indicates external memory, large code model)
1 2 VID - USB Vendor ID (little-endian) -> 0x09C0 (Genpix) 1 2 VID - USB Vendor ID (little-endian) -> 0x09C0 (Genpix)
3 2 PID - USB Product ID (little-endian) 3 2 PID - USB Product ID (little-endian)
5 2 DID - Device ID (little-endian) -> 0x0000 5 2 DID - Device ID (little-endian) -> 0x0000
7 1 config - 0x40 (400kHz I2C bus speed) 7 1 config - 0x40 (400kHz I2C bus speed)
``` ```
**Followed by code segments:** **Followed by code segments:**
``` ```
Offset Size Field Offset Size Field
------ ---------- ----- ------ ---------- -----
0 2 seg_len - Segment length (big-endian) 0 2 seg_len - Segment length (big-endian)
2 2 seg_addr - Target RAM address (big-endian) 2 2 seg_addr - Target RAM address (big-endian)
4 seg_len data[] - Code/data bytes 4 seg_len data[] - Code/data bytes
``` ```
**Terminated by:** **Terminated by:**
``` ```
0 2 0x8001 - High bit set signals terminator 0 2 0x8001 - High bit set signals terminator
2 2 entry - Entry point address (big-endian) -> 0xE600 (CPUCS) 2 2 entry - Entry point address (big-endian) -> 0xE600 (CPUCS)
``` ```
### Decoded C2 Headers ### Decoded C2 Headers
| File | VID | PID | Segments | Code Size | Entry | | File | VID | PID | Segments | Code Size | Entry |
|------|-----|-----|----------|-----------|-------| |------|-----|-----|----------|-----------|-------|
| `skywalker1_eeprom.bin` (v2.06) | 0x09C0 | **0x0203** | 10 | 9,472 bytes | 0xE600 | | `skywalker1_eeprom.bin` (v2.06) | 0x09C0 | **0x0203** | 10 | 9,472 bytes | 0xE600 |
| `sw1_v213_fw_1_c2.bin` (v2.13.1) | 0x09C0 | **0x0203** | 10 | 9,322 bytes | 0xE600 | | `sw1_v213_fw_1_c2.bin` (v2.13.1) | 0x09C0 | **0x0203** | 10 | 9,322 bytes | 0xE600 |
| `sw1_v213_fw_2_c2.bin` (v2.13.2) | 0x09C0 | **0x0203** | 10 | 9,377 bytes | 0xE600 | | `sw1_v213_fw_2_c2.bin` (v2.13.2) | 0x09C0 | **0x0203** | 10 | 9,377 bytes | 0xE600 |
| `sw1_v213_fw_3_c2.bin` (v2.13.3) | 0x09C0 | **0x0203** | 10 | 9,369 bytes | 0xE600 | | `sw1_v213_fw_3_c2.bin` (v2.13.3) | 0x09C0 | **0x0203** | 10 | 9,369 bytes | 0xE600 |
| `rev2_v210_fw_1_c2.bin` (Rev2 v2.10) | 0x09C0 | **0x0202** | 9 | 8,843 bytes | 0xE600 | | `rev2_v210_fw_1_c2.bin` (Rev2 v2.10) | 0x09C0 | **0x0202** | 9 | 8,843 bytes | 0xE600 |
Note: The PID in the C2 header determines the USB Product ID that the FX2 enumerates with after booting. SkyWalker-1 variants all use PID 0x0203, while Rev.2 uses 0x0202. Note: The PID in the C2 header determines the USB Product ID that the FX2 enumerates with after booting. SkyWalker-1 variants all use PID 0x0203, while Rev.2 uses 0x0202.
### C2 Segment Layout (All SkyWalker-1 Variants) ### C2 Segment Layout (All SkyWalker-1 Variants)
All SkyWalker-1 C2 files use uniform 1023-byte segments (except the last): All SkyWalker-1 C2 files use uniform 1023-byte segments (except the last):
``` ```
Segment Address Length Notes Segment Address Length Notes
------- ------- ------ ----- ------- ------- ------ -----
1 0x0000 1023 Contains reset vector, interrupt handlers 1 0x0000 1023 Contains reset vector, interrupt handlers
2 0x03FF 1023 2 0x03FF 1023
3 0x07FE 1023 3 0x07FE 1023
4 0x0BFD 1023 4 0x0BFD 1023
5 0x0FFC 1023 5 0x0FFC 1023
6 0x13FB 1023 6 0x13FB 1023
7 0x17FA 1023 7 0x17FA 1023
8 0x1BF9 1023 8 0x1BF9 1023
9 0x1FF8 1023 9 0x1FF8 1023
10 0x23F7 varies (115-265 bytes depending on version) 10 0x23F7 varies (115-265 bytes depending on version)
``` ```
The 1023-byte segment size is the maximum the FX2 I2C EEPROM boot ROM reads per transaction (limited by internal buffer). The 1023-byte segment size is the maximum the FX2 I2C EEPROM boot ROM reads per transaction (limited by internal buffer).
--- ---
## 5. Format Incompatibility: C2 vs Kernel Hexline ## 5. Format Incompatibility: C2 vs Kernel Hexline
The firmware as stored in EEPROM (C2 format) is **structurally different** from what the kernel expects (binary hexline format). They cannot be used interchangeably. The firmware as stored in EEPROM (C2 format) is **structurally different** from what the kernel expects (binary hexline format). They cannot be used interchangeably.
| Property | C2 (EEPROM) | Hexline (Kernel FW01) | | Property | C2 (EEPROM) | Hexline (Kernel FW01) |
|----------|-------------|-----------------------| |----------|-------------|-----------------------|
| Header | 8-byte C2 with VID/PID/DID | None | | Header | 8-byte C2 with VID/PID/DID | None |
| Address encoding | Big-endian 16-bit per segment | Little-endian split (addr_lo, addr_hi) per record | | Address encoding | Big-endian 16-bit per segment | Little-endian split (addr_lo, addr_hi) per record |
| Data chunking | 1023-byte segments | Typically 16-byte records | | Data chunking | 1023-byte segments | Typically 16-byte records |
| Record overhead | 4 bytes per segment | 5 bytes per record | | Record overhead | 4 bytes per segment | 5 bytes per record |
| Terminator | 0x80xx + entry point | Type 0x01 EOF record | | Terminator | 0x80xx + entry point | Type 0x01 EOF record |
| Entry point | Explicit in terminator | Implicit (CPUCS at 0xE600) | | Entry point | Explicit in terminator | Implicit (CPUCS at 0xE600) |
However, the **payload data is identical**. The "flat" extracted firmware (C2 segments concatenated, headers stripped) contains the same 8051 machine code that a hexline-format FW01 would carry. The difference is purely container format. However, the **payload data is identical**. The "flat" extracted firmware (C2 segments concatenated, headers stripped) contains the same 8051 machine code that a hexline-format FW01 would carry. The difference is purely container format.
### Theoretical Conversion: C2 -> Hexline ### Theoretical Conversion: C2 -> Hexline
A C2 file can be converted to the kernel's hexline format by: A C2 file can be converted to the kernel's hexline format by:
1. Strip the 8-byte C2 header 1. Strip the 8-byte C2 header
2. For each segment: emit 16-byte hexline records with type=0x00, splitting the segment data 2. For each segment: emit 16-byte hexline records with type=0x00, splitting the segment data
3. Append an EOF record (len=0, type=0x01) 3. Append an EOF record (len=0, type=0x01)
The resulting file would be the equivalent of `dvb-usb-gp8psk-01.fw` for that firmware version. For the v2.06 EEPROM (9,472 code bytes), this produces approximately 12,442 bytes in hexline format. The resulting file would be the equivalent of `dvb-usb-gp8psk-01.fw` for that firmware version. For the v2.06 EEPROM (9,472 code bytes), this produces approximately 12,442 bytes in hexline format.
--- ---
## 6. FW02 (BCM4500 Demodulator Firmware) Analysis ## 6. FW02 (BCM4500 Demodulator Firmware) Analysis
### Loading Protocol ### Loading Protocol
From the kernel source (`gp8psk_load_bcm4500fw()`), FW02 uses a **custom chunk protocol** sent via USB bulk endpoint: From the kernel source (`gp8psk_load_bcm4500fw()`), FW02 uses a **custom chunk protocol** sent via USB bulk endpoint:
``` ```
Chunk format: Chunk format:
Byte 0: payload_length (N) Byte 0: payload_length (N)
Bytes 1-3: header/address bytes (3 bytes) Bytes 1-3: header/address bytes (3 bytes)
Bytes 4..N+3: payload data Bytes 4..N+3: payload data
Total chunk size = ptr[0] + 4 = payload_length + 4 Total chunk size = ptr[0] + 4 = payload_length + 4
Maximum chunk size: 64 bytes (USB control transfer limit) Maximum chunk size: 64 bytes (USB control transfer limit)
Terminator: single byte 0xFF Terminator: single byte 0xFF
``` ```
The loading sequence: The loading sequence:
1. Send `LOAD_BCM4500` command (0x88, wValue=1) to initiate transfer mode 1. Send `LOAD_BCM4500` command (0x88, wValue=1) to initiate transfer mode
2. Iterate through chunks until 0xFF terminator 2. Iterate through chunks until 0xFF terminator
3. Each chunk is sent via `dvb_usb_generic_write()` (bulk endpoint 0x01) 3. Each chunk is sent via `dvb_usb_generic_write()` (bulk endpoint 0x01)
### Relevance to SkyWalker-1 ### Relevance to SkyWalker-1
**FW02 is irrelevant for SkyWalker-1.** The BCM4500 demodulator firmware is burned into ROM on all Rev.2 and later hardware. The kernel driver explicitly checks: **FW02 is irrelevant for SkyWalker-1.** The BCM4500 demodulator firmware is burned into ROM on all Rev.2 and later hardware. The kernel driver explicitly checks:
```c ```c
if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) // 0x0201 only if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) // 0x0201 only
``` ```
On the SkyWalker-1 (PID 0x0203), command 0x88 (`LOAD_BCM4500`) routes to the STALL handler in the FX2 firmware -- confirmed by Ghidra disassembly of all extracted firmware versions. On the SkyWalker-1 (PID 0x0203), command 0x88 (`LOAD_BCM4500`) routes to the STALL handler in the FX2 firmware -- confirmed by Ghidra disassembly of all extracted firmware versions.
--- ---
## 7. Firmware Version Identification ## 7. Firmware Version Identification
### Kernel dmesg Output ### Kernel dmesg Output
``` ```
gp8psk: FW Version = 2.06.4 (0x20604) Build 2007/07/13 gp8psk: FW Version = 2.06.4 (0x20604) Build 2007/07/13
gp8psk: usb in 149 operation failed. gp8psk: usb in 149 operation failed.
gp8psk: failed to get FPGA version gp8psk: failed to get FPGA version
gp8psk_fe: Frontend attached gp8psk_fe: Frontend attached
gp8psk: found Genpix USB device pID = 203 (hex) gp8psk: found Genpix USB device pID = 203 (hex)
``` ```
The version is read via USB command `GET_FW_VERS` (0x92), which returns 6 bytes: `[minor, build, major, day, month, year-2000]`. The FX2 firmware computes and returns this at runtime from internal constants -- the version bytes are not stored as a simple searchable pattern in the binary. The version is read via USB command `GET_FW_VERS` (0x92), which returns 6 bytes: `[minor, build, major, day, month, year-2000]`. The FX2 firmware computes and returns this at runtime from internal constants -- the version bytes are not stored as a simple searchable pattern in the binary.
### Kernel Firmware Revision Constants ### Kernel Firmware Revision Constants
From `gp8psk-fe.h`: From `gp8psk-fe.h`:
```c ```c
#define GP8PSK_FW_REV1 0x020604 // v2.06.4 #define GP8PSK_FW_REV1 0x020604 // v2.06.4
#define GP8PSK_FW_REV2 0x020704 // v2.07.4 #define GP8PSK_FW_REV2 0x020704 // v2.07.4
``` ```
The kernel only knows about two firmware revisions. Our v2.10 and v2.13 firmwares are significantly newer and unknown to the kernel. The kernel only knows about two firmware revisions. Our v2.10 and v2.13 firmwares are significantly newer and unknown to the kernel.
### FPGA Version Failure ### FPGA Version Failure
``` ```
gp8psk: usb in 149 operation failed. gp8psk: usb in 149 operation failed.
gp8psk: failed to get FPGA version gp8psk: failed to get FPGA version
``` ```
Command 0x95 (`GET_FPGA_VERS`, decimal 149) fails on the SkyWalker-1. This command likely targets a separate FPGA that exists only on certain hardware revisions, or the SkyWalker-1 firmware does not implement this vendor command. The driver logs the failure but continues normally. Command 0x95 (`GET_FPGA_VERS`, decimal 149) fails on the SkyWalker-1. This command likely targets a separate FPGA that exists only on certain hardware revisions, or the SkyWalker-1 firmware does not implement this vendor command. The driver logs the failure but continues normally.
### Version Strings in Firmware ### Version Strings in Firmware
No human-readable version strings were found in the v2.06 or Rev2 v2.10 firmware binaries. The v2.13.x variants contain a single notable string: No human-readable version strings were found in the v2.06 or Rev2 v2.10 firmware binaries. The v2.13.x variants contain a single notable string:
``` ```
Offset 0x1880 (all three v2.13 sub-variants): Offset 0x1880 (all three v2.13 sub-variants):
"Tampering is detected. Attempt is logged. Warranty is voided ! \n" "Tampering is detected. Attempt is logged. Warranty is voided ! \n"
``` ```
Followed by bytes `01 10 aa 82 02 41 41 83` -- likely I2C register write commands related to the tampering detection/logging mechanism. This string is absent from v2.06 and v2.10 firmware, indicating Genpix added anti-tampering measures in the v2.13 firmware generation. Followed by bytes `01 10 aa 82 02 41 41 83` -- likely I2C register write commands related to the tampering detection/logging mechanism. This string is absent from v2.06 and v2.10 firmware, indicating Genpix added anti-tampering measures in the v2.13 firmware generation.
--- ---
## 8. Binary Comparison: Extracted Firmware Dumps ## 8. Binary Comparison: Extracted Firmware Dumps
### File Sizes ### File Sizes
| File | Size | Format | | File | Size | Format |
|------|------|--------| |------|------|--------|
| `skywalker1_eeprom_flat.bin` (v2.06.4) | 9,472 bytes | Flat binary | | `skywalker1_eeprom_flat.bin` (v2.06.4) | 9,472 bytes | Flat binary |
| `sw1_v213_fw_1_flat.bin` (v2.13.1) | 9,322 bytes | Flat binary | | `sw1_v213_fw_1_flat.bin` (v2.13.1) | 9,322 bytes | Flat binary |
| `sw1_v213_fw_2_flat.bin` (v2.13.2) | 9,377 bytes | Flat binary | | `sw1_v213_fw_2_flat.bin` (v2.13.2) | 9,377 bytes | Flat binary |
| `sw1_v213_fw_3_flat.bin` (v2.13.3) | 9,369 bytes | Flat binary | | `sw1_v213_fw_3_flat.bin` (v2.13.3) | 9,369 bytes | Flat binary |
| `rev2_v210_fw_1_flat.bin` (Rev2 v2.10.4) | 8,843 bytes | Flat binary | | `rev2_v210_fw_1_flat.bin` (Rev2 v2.10.4) | 8,843 bytes | Flat binary |
### Byte-Level Similarity Matrix ### Byte-Level Similarity Matrix
Percentage of matching bytes within the shared length of each pair: Percentage of matching bytes within the shared length of each pair:
| | v2.06 | v2.13.1 | v2.13.2 | v2.13.3 | Rev2 v2.10 | | | v2.06 | v2.13.1 | v2.13.2 | v2.13.3 | Rev2 v2.10 |
|---|---|---|---|---|---| |---|---|---|---|---|---|
| **v2.06** | -- | 4.8% | 4.3% | 4.3% | 6.0% | | **v2.06** | -- | 4.8% | 4.3% | 4.3% | 6.0% |
| **v2.13.1** | | -- | 57.2% | 59.4% | 8.0% | | **v2.13.1** | | -- | 57.2% | 59.4% | 8.0% |
| **v2.13.2** | | | -- | 83.5% | 5.8% | | **v2.13.2** | | | -- | 83.5% | 5.8% |
| **v2.13.3** | | | | -- | 5.8% | | **v2.13.3** | | | | -- | 5.8% |
| **Rev2 v2.10** | | | | | -- | | **Rev2 v2.10** | | | | | -- |
### Differing Byte Counts ### Differing Byte Counts
| Pair | Different Bytes | Shared Length | Mismatch Rate | | Pair | Different Bytes | Shared Length | Mismatch Rate |
|------|----------------|---------------|---------------| |------|----------------|---------------|---------------|
| v2.06 vs v2.13.1 | 8,878 | 9,322 | 95.2% | | v2.06 vs v2.13.1 | 8,878 | 9,322 | 95.2% |
| v2.06 vs Rev2 v2.10 | 8,312 | 8,843 | 94.0% | | v2.06 vs Rev2 v2.10 | 8,312 | 8,843 | 94.0% |
| v2.13.1 vs Rev2 v2.10 | 8,133 | 8,843 | 92.0% | | v2.13.1 vs Rev2 v2.10 | 8,133 | 8,843 | 92.0% |
| v2.13.1 vs v2.13.2 | 3,994 | 9,322 | 42.8% | | v2.13.1 vs v2.13.2 | 3,994 | 9,322 | 42.8% |
| v2.13.2 vs v2.13.3 | 1,549 | 9,369 | 16.5% | | v2.13.2 vs v2.13.3 | 1,549 | 9,369 | 16.5% |
### Longest Identical Run ### Longest Identical Run
| Pair | Longest Match | Starting Offset | | Pair | Longest Match | Starting Offset |
|------|--------------|-----------------| |------|--------------|-----------------|
| v2.06 vs v2.13.1 | 22 bytes | 0x0055 | | v2.06 vs v2.13.1 | 22 bytes | 0x0055 |
| v2.06 vs Rev2 v2.10 | 36 bytes | 0x080C | | v2.06 vs Rev2 v2.10 | 36 bytes | 0x080C |
### Interpretation ### Interpretation
The very low byte-level similarity between different major versions (v2.06 vs v2.10 vs v2.13) indicates **complete recompilation** with different toolchains or linker configurations. Functions are relocated to different addresses even when their logic is identical. The first byte of every flat dump already differs (the second byte of the reset vector LJMP target), confirming different code layout starting from the entry point. The very low byte-level similarity between different major versions (v2.06 vs v2.10 vs v2.13) indicates **complete recompilation** with different toolchains or linker configurations. Functions are relocated to different addresses even when their logic is identical. The first byte of every flat dump already differs (the second byte of the reset vector LJMP target), confirming different code layout starting from the entry point.
Within the v2.13 family, FW2 and FW3 share 83.5% of bytes, reflecting minor hardware-specific changes (parallel bus timing, GPIO defaults, IRAM layout). FW1 differs more substantially (57-59% match) because it targets fundamentally different hardware (I2C vs parallel bus demodulator interface). Within the v2.13 family, FW2 and FW3 share 83.5% of bytes, reflecting minor hardware-specific changes (parallel bus timing, GPIO defaults, IRAM layout). FW1 differs more substantially (57-59% match) because it targets fundamentally different hardware (I2C vs parallel bus demodulator interface).
--- ---
## 9. Other Extracted Files ## 9. Other Extracted Files
### FX2 Internal ROM (`skywalker1_fx2_internal.bin`, 8,192 bytes) ### FX2 Internal ROM (`skywalker1_fx2_internal.bin`, 8,192 bytes)
The FX2 internal ROM dump does **not** contain program code in a recognizable 8051 format. It appears to be the FX2's built-in boot ROM (mask ROM), which handles: The FX2 internal ROM dump does **not** contain program code in a recognizable 8051 format. It appears to be the FX2's built-in boot ROM (mask ROM), which handles:
- USB enumeration in "unconfigured" state - USB enumeration in "unconfigured" state
- I2C EEPROM boot loading (reading C2 format images) - I2C EEPROM boot loading (reading C2 format images)
- 0xA0 vendor request handling (RAM write for host firmware upload) - 0xA0 vendor request handling (RAM write for host firmware upload)
This ROM is identical across all Cypress CY7C68013A chips and is not Genpix-specific. This ROM is identical across all Cypress CY7C68013A chips and is not Genpix-specific.
### FX2 External Memory (`skywalker1_fx2_external.bin`, 65,536 bytes) ### FX2 External Memory (`skywalker1_fx2_external.bin`, 65,536 bytes)
A 64KB dump of the FX2's full external address space. The first ~9.5KB contains the same code as `skywalker1_eeprom_flat.bin`; the remainder is the full 64KB memory space including RAM, SFR shadows, and unused regions. A 64KB dump of the FX2's full external address space. The first ~9.5KB contains the same code as `skywalker1_eeprom_flat.bin`; the remainder is the full 64KB memory space including RAM, SFR shadows, and unused regions.
--- ---
## 10. Summary of Findings ## 10. Summary of Findings
1. **Firmware files `dvb-usb-gp8psk-01.fw` and `dvb-usb-gp8psk-02.fw` do not exist** on this system, in linux-firmware, or in any standard distribution. They were never open-sourced. 1. **Firmware files `dvb-usb-gp8psk-01.fw` and `dvb-usb-gp8psk-02.fw` do not exist** on this system, in linux-firmware, or in any standard distribution. They were never open-sourced.
2. **SkyWalker-1 does not need either file.** The kernel driver only requests FW01 for Rev.1 Cold devices (PID 0x0200) and FW02 for Rev.1 Warm devices (PID 0x0201). The SkyWalker-1 boots from its onboard EEPROM and appears directly as a "warm" device (PID 0x0203). 2. **SkyWalker-1 does not need either file.** The kernel driver only requests FW01 for Rev.1 Cold devices (PID 0x0200) and FW02 for Rev.1 Warm devices (PID 0x0201). The SkyWalker-1 boots from its onboard EEPROM and appears directly as a "warm" device (PID 0x0203).
3. **FW01 format** would be DVB-USB binary hexline records (a compact binary encoding of Intel HEX), loaded via Cypress FX2 0xA0 vendor requests to CPUCS. Our extracted dumps are in Cypress C2 EEPROM boot format -- different container, identical payload. 3. **FW01 format** would be DVB-USB binary hexline records (a compact binary encoding of Intel HEX), loaded via Cypress FX2 0xA0 vendor requests to CPUCS. Our extracted dumps are in Cypress C2 EEPROM boot format -- different container, identical payload.
4. **FW02 format** is a custom Genpix chunk protocol (length byte + 3 header bytes + data, terminated by 0xFF), loaded via USB bulk transfers after a LOAD_BCM4500 command (0x88). This is only relevant for Rev.1 hardware. 4. **FW02 format** is a custom Genpix chunk protocol (length byte + 3 header bytes + data, terminated by 0xFF), loaded via USB bulk transfers after a LOAD_BCM4500 command (0x88). This is only relevant for Rev.1 hardware.
5. **The currently running firmware** is v2.06.4 (build 2007/07/13), matching the kernel's `GP8PSK_FW_REV1` constant (0x020604). This is the original factory firmware burned into the SkyWalker-1 EEPROM. 5. **The currently running firmware** is v2.06.4 (build 2007/07/13), matching the kernel's `GP8PSK_FW_REV1` constant (0x020604). This is the original factory firmware burned into the SkyWalker-1 EEPROM.
6. **The v2.13 firmware** (extracted from the Windows updater) adds anti-tampering detection and supports three different hardware sub-variants. The v2.10 Rev.2 firmware is for a different product (PID 0x0202). 6. **The v2.13 firmware** (extracted from the Windows updater) adds anti-tampering detection and supports three different hardware sub-variants. The v2.10 Rev.2 firmware is for a different product (PID 0x0202).
--- ---
## Sources ## Sources
- Linux kernel 6.16.5 source: `drivers/media/usb/dvb-usb/gp8psk.c`, `gp8psk.h` - Linux kernel 6.16.5 source: `drivers/media/usb/dvb-usb/gp8psk.c`, `gp8psk.h`
- Linux kernel 6.16.5 source: `drivers/media/dvb-frontends/gp8psk-fe.h` - Linux kernel 6.16.5 source: `drivers/media/dvb-frontends/gp8psk-fe.h`
- Linux kernel 6.16.5 source: `drivers/media/usb/dvb-usb/dvb-usb-firmware.c` - Linux kernel 6.16.5 source: `drivers/media/usb/dvb-usb/dvb-usb-firmware.c`
- Linux kernel 6.16.5 source: `include/linux/ihex.h` - Linux kernel 6.16.5 source: `include/linux/ihex.h`
- Firmware dumps: `/home/rpm/claude/ham/satellite/genpix/skywalker-1/firmware-dump/` - Firmware dumps: `/home/rpm/claude/ham/satellite/genpix/skywalker-1/firmware-dump/`
- `dmesg` output from running SkyWalker-1 hardware - `dmesg` output from running SkyWalker-1 hardware
- linux-firmware git repository (https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git) - linux-firmware git repository (https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git)

View File

@ -1,8 +1,8 @@
{ {
"mcpServers": { "mcpServers": {
"skywalker-mcp": { "skywalker-mcp": {
"command": "uv", "command": "uv",
"args": ["run", "--directory", ".", "skywalker-mcp"] "args": ["run", "--directory", ".", "skywalker-mcp"]
} }
} }
} }

View File

@ -1,35 +1,35 @@
[build-system] [build-system]
requires = ["hatchling"] requires = ["hatchling"]
build-backend = "hatchling.build" build-backend = "hatchling.build"
[project] [project]
name = "skywalker-mcp" name = "skywalker-mcp"
version = "2026.2.17" version = "2026.2.17"
description = "MCP server for the Genpix SkyWalker-1 DVB-S USB receiver" description = "MCP server for the Genpix SkyWalker-1 DVB-S USB receiver"
requires-python = ">=3.11" requires-python = ">=3.11"
authors = [{name = "Ryan Malloy", email = "ryan@supported.systems"}] authors = [{name = "Ryan Malloy", email = "ryan@supported.systems"}]
dependencies = [ dependencies = [
"fastmcp>=2.0", "fastmcp>=2.0",
"pyusb>=1.3", "pyusb>=1.3",
] ]
[project.scripts] [project.scripts]
skywalker-mcp = "skywalker_mcp.server:main" skywalker-mcp = "skywalker_mcp.server:main"
[tool.hatch.build.targets.wheel] [tool.hatch.build.targets.wheel]
packages = ["src/skywalker_mcp"] packages = ["src/skywalker_mcp"]
[project.optional-dependencies] [project.optional-dependencies]
dev = [ dev = [
"pytest>=8.0", "pytest>=8.0",
"pytest-asyncio>=0.24", "pytest-asyncio>=0.24",
"ruff>=0.9", "ruff>=0.9",
] ]
[tool.ruff] [tool.ruff]
target-version = "py311" target-version = "py311"
line-length = 100 line-length = 100
[tool.pytest.ini_options] [tool.pytest.ini_options]
testpaths = ["tests"] testpaths = ["tests"]
asyncio_mode = "auto" asyncio_mode = "auto"

View File

@ -1,3 +1,3 @@
"""MCP server for the Genpix SkyWalker-1 DVB-S USB receiver.""" """MCP server for the Genpix SkyWalker-1 DVB-S USB receiver."""
__version__ = "2026.2.17" __version__ = "2026.2.17"

View File

@ -1,136 +1,136 @@
"""Mock SkyWalker1 device for testing without USB hardware. """Mock SkyWalker1 device for testing without USB hardware.
Used by: Used by:
- Server lifespan when SKYWALKER_MOCK=1 is set (integration testing) - Server lifespan when SKYWALKER_MOCK=1 is set (integration testing)
- conftest.py fixtures for unit tests - conftest.py fixtures for unit tests
""" """
class MockSkyWalker1: class MockSkyWalker1:
"""Returns plausible data for all SkyWalker1 API calls without USB hardware.""" """Returns plausible data for all SkyWalker1 API calls without USB hardware."""
def __init__(self, verbose=False): def __init__(self, verbose=False):
self.verbose = verbose self.verbose = verbose
self._motor_halted = False self._motor_halted = False
self._armed = False self._armed = False
self._lnb_on = True self._lnb_on = True
self._calls = [] self._calls = []
def _record(self, method, *args, **kwargs): def _record(self, method, *args, **kwargs):
self._calls.append((method, args, kwargs)) self._calls.append((method, args, kwargs))
def open(self): def open(self):
self._record("open") self._record("open")
def close(self): def close(self):
self._record("close") self._record("close")
def ensure_booted(self): def ensure_booted(self):
self._record("ensure_booted") self._record("ensure_booted")
def get_fw_version(self): def get_fw_version(self):
self._record("get_fw_version") self._record("get_fw_version")
return {"version": "3.05.0-mock", "date": "2026-02-17", "raw": b"\x03\x05\x00"} return {"version": "3.05.0-mock", "date": "2026-02-17", "raw": b"\x03\x05\x00"}
def get_config(self): def get_config(self):
self._record("get_config") self._record("get_config")
return 0x3F return 0x3F
def get_usb_speed(self): def get_usb_speed(self):
self._record("get_usb_speed") self._record("get_usb_speed")
return 2 return 2
def get_serial_number(self): def get_serial_number(self):
self._record("get_serial_number") self._record("get_serial_number")
return bytes([0xDE, 0xAD, 0xBE, 0xEF]) return bytes([0xDE, 0xAD, 0xBE, 0xEF])
def get_last_error(self): def get_last_error(self):
self._record("get_last_error") self._record("get_last_error")
return 0x00 return 0x00
def signal_monitor(self): def signal_monitor(self):
self._record("signal_monitor") self._record("signal_monitor")
return { return {
"snr_raw": 200, "snr_db": 8.5, "snr_pct": 42.5, "snr_raw": 200, "snr_db": 8.5, "snr_pct": 42.5,
"agc1": 1200, "agc2": 800, "power_db": -45.3, "agc1": 1200, "agc2": 800, "power_db": -45.3,
"locked": True, "lock": 0x1F, "status": 0x01, "locked": True, "lock": 0x1F, "status": 0x01,
} }
def get_stream_diag(self, reset=False): def get_stream_diag(self, reset=False):
self._record("get_stream_diag", reset=reset) self._record("get_stream_diag", reset=reset)
return {"poll_count": 100, "overflow_count": 0, "sync_loss": 0, "armed": self._armed} return {"poll_count": 100, "overflow_count": 0, "sync_loss": 0, "armed": self._armed}
def sweep_spectrum(self, start_mhz, stop_mhz, step_mhz=5.0, dwell_ms=15): def sweep_spectrum(self, start_mhz, stop_mhz, step_mhz=5.0, dwell_ms=15):
self._record("sweep_spectrum", start_mhz, stop_mhz, step_mhz=step_mhz, dwell_ms=dwell_ms) self._record("sweep_spectrum", start_mhz, stop_mhz, step_mhz=step_mhz, dwell_ms=dwell_ms)
n_points = int((stop_mhz - start_mhz) / step_mhz) + 1 n_points = int((stop_mhz - start_mhz) / step_mhz) + 1
freqs = [start_mhz + i * step_mhz for i in range(n_points)] freqs = [start_mhz + i * step_mhz for i in range(n_points)]
powers = [] powers = []
for f in freqs: for f in freqs:
base = -50.0 base = -50.0
if abs(f - 1420.0) < 5: if abs(f - 1420.0) < 5:
base += 8.0 * (1.0 - abs(f - 1420.0) / 5.0) base += 8.0 * (1.0 - abs(f - 1420.0) / 5.0)
powers.append(base) powers.append(base)
raw = [(int((p + 60) * 100), 0) for p in powers] raw = [(int((p + 60) * 100), 0) for p in powers]
return freqs, powers, raw return freqs, powers, raw
def tune_monitor(self, sr_sps, freq_khz, mod_idx, fec_idx, dwell_ms): def tune_monitor(self, sr_sps, freq_khz, mod_idx, fec_idx, dwell_ms):
self._record("tune_monitor", sr_sps, freq_khz, mod_idx, fec_idx, dwell_ms) self._record("tune_monitor", sr_sps, freq_khz, mod_idx, fec_idx, dwell_ms)
return { return {
"snr_raw": 180, "snr_db": 7.8, "snr_pct": 39.0, "snr_raw": 180, "snr_db": 7.8, "snr_pct": 39.0,
"agc1": 1100, "agc2": 750, "power_db": -46.1, "agc1": 1100, "agc2": 750, "power_db": -46.1,
"locked": True, "lock": 0x1F, "status": 0x01, "locked": True, "lock": 0x1F, "status": 0x01,
"dwell_ms": dwell_ms, "dwell_ms": dwell_ms,
} }
def adaptive_blind_scan(self, freq_khz, sr_min, sr_max, sr_step): def adaptive_blind_scan(self, freq_khz, sr_min, sr_max, sr_step):
self._record("adaptive_blind_scan", freq_khz, sr_min, sr_max, sr_step) self._record("adaptive_blind_scan", freq_khz, sr_min, sr_max, sr_step)
return {"freq_khz": freq_khz, "locked": True, "sr_sps": 20000000} return {"freq_khz": freq_khz, "locked": True, "sr_sps": 20000000}
def motor_halt(self): def motor_halt(self):
self._record("motor_halt") self._record("motor_halt")
self._motor_halted = True self._motor_halted = True
def motor_drive_east(self, steps): def motor_drive_east(self, steps):
self._record("motor_drive_east", steps) self._record("motor_drive_east", steps)
self._motor_halted = False self._motor_halted = False
def motor_drive_west(self, steps): def motor_drive_west(self, steps):
self._record("motor_drive_west", steps) self._record("motor_drive_west", steps)
self._motor_halted = False self._motor_halted = False
def motor_goto_position(self, slot): def motor_goto_position(self, slot):
self._record("motor_goto_position", slot) self._record("motor_goto_position", slot)
def motor_goto_x(self, observer_lon, sat_lon): def motor_goto_x(self, observer_lon, sat_lon):
self._record("motor_goto_x", observer_lon, sat_lon) self._record("motor_goto_x", observer_lon, sat_lon)
def motor_store_position(self, slot): def motor_store_position(self, slot):
self._record("motor_store_position", slot) self._record("motor_store_position", slot)
def start_intersil(self, on=True): def start_intersil(self, on=True):
self._record("start_intersil", on=on) self._record("start_intersil", on=on)
self._lnb_on = on self._lnb_on = on
def set_lnb_voltage(self, high): def set_lnb_voltage(self, high):
self._record("set_lnb_voltage", high) self._record("set_lnb_voltage", high)
def set_22khz_tone(self, on): def set_22khz_tone(self, on):
self._record("set_22khz_tone", on) self._record("set_22khz_tone", on)
def i2c_bus_scan(self): def i2c_bus_scan(self):
self._record("i2c_bus_scan") self._record("i2c_bus_scan")
return [0x08, 0x10, 0x51] return [0x08, 0x10, 0x51]
def i2c_raw_read(self, slave, register): def i2c_raw_read(self, slave, register):
self._record("i2c_raw_read", slave, register) self._record("i2c_raw_read", slave, register)
return 0xAB return 0xAB
def arm_transfer(self, on): def arm_transfer(self, on):
self._record("arm_transfer", on) self._record("arm_transfer", on)
self._armed = on self._armed = on
def read_stream(self, timeout=500): def read_stream(self, timeout=500):
self._record("read_stream", timeout=timeout) self._record("read_stream", timeout=timeout)
if self._armed: if self._armed:
return bytes([0x47, 0x00, 0x00, 0x10] + [0xFF] * 184) return bytes([0x47, 0x00, 0x00, 0x10] + [0xFF] * 184)
return None return None

File diff suppressed because it is too large Load Diff

View File

@ -1,47 +1,47 @@
"""Shared fixtures for skywalker-mcp tests.""" """Shared fixtures for skywalker-mcp tests."""
from unittest.mock import MagicMock from unittest.mock import MagicMock
import pytest import pytest
import skywalker_mcp.server as srv import skywalker_mcp.server as srv
from skywalker_mcp.mock_device import MockSkyWalker1 from skywalker_mcp.mock_device import MockSkyWalker1
from skywalker_mcp.server import DeviceBridge from skywalker_mcp.server import DeviceBridge
class MockContext: class MockContext:
"""Minimal mock of FastMCP Context for direct tool function calls. """Minimal mock of FastMCP Context for direct tool function calls.
Provides the bridge via request_context.lifespan_context["bridge"], Provides the bridge via request_context.lifespan_context["bridge"],
matching what _get_bridge(ctx) expects. matching what _get_bridge(ctx) expects.
""" """
def __init__(self, bridge: DeviceBridge): def __init__(self, bridge: DeviceBridge):
self.request_context = MagicMock() self.request_context = MagicMock()
self.request_context.lifespan_context = {"bridge": bridge} self.request_context.lifespan_context = {"bridge": bridge}
self._progress = [] self._progress = []
async def report_progress(self, current, total): async def report_progress(self, current, total):
self._progress.append((current, total)) self._progress.append((current, total))
@pytest.fixture @pytest.fixture
def mock_device(): def mock_device():
"""Provide a fresh MockSkyWalker1 instance.""" """Provide a fresh MockSkyWalker1 instance."""
return MockSkyWalker1() return MockSkyWalker1()
@pytest.fixture @pytest.fixture
def bridge(mock_device): def bridge(mock_device):
"""Provide a DeviceBridge wrapping the mock device.""" """Provide a DeviceBridge wrapping the mock device."""
b = DeviceBridge(mock_device) b = DeviceBridge(mock_device)
srv._bridge = b srv._bridge = b
yield b yield b
b.cancel_motor_watchdog() b.cancel_motor_watchdog()
srv._bridge = None srv._bridge = None
@pytest.fixture @pytest.fixture
def ctx(bridge): def ctx(bridge):
"""Provide a MockContext wired to the bridge.""" """Provide a MockContext wired to the bridge."""
return MockContext(bridge) return MockContext(bridge)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,3 @@
node_modules node_modules
dist dist
.env .env

View File

@ -1,11 +1,11 @@
:80 { :80 {
root * /srv root * /srv
encode gzip encode gzip
handle /health { handle /health {
respond "ok" 200 respond "ok" 200
} }
try_files {path} {path}/index.html {path}/ /index.html try_files {path} {path}/index.html {path}/ /index.html
file_server file_server
} }

View File

@ -1,24 +1,24 @@
# ── base: shared dependency install ────────────────────────────── # ── base: shared dependency install ──────────────────────────────
FROM node:20-slim AS base FROM node:20-slim AS base
WORKDIR /app WORKDIR /app
COPY package.json package-lock.json ./ COPY package.json package-lock.json ./
RUN npm ci RUN npm ci
COPY . . COPY . .
# ── dev: Astro dev server with HMR ───────────────────────────── # ── dev: Astro dev server with HMR ─────────────────────────────
FROM base AS dev FROM base AS dev
ENV HOST=0.0.0.0 ENV HOST=0.0.0.0
EXPOSE 4321 EXPOSE 4321
CMD ["npx", "astro", "dev", "--host", "0.0.0.0", "--port", "4321"] CMD ["npx", "astro", "dev", "--host", "0.0.0.0", "--port", "4321"]
# ── build: static site generation ─────────────────────────────── # ── build: static site generation ───────────────────────────────
FROM base AS build FROM base AS build
RUN npx astro build RUN npx astro build
# ── prod: Caddy serving static files ─────────────────────────── # ── prod: Caddy serving static files ───────────────────────────
FROM caddy:2-alpine AS prod FROM caddy:2-alpine AS prod
COPY Caddyfile /etc/caddy/Caddyfile COPY Caddyfile /etc/caddy/Caddyfile
COPY --from=build /app/dist /srv COPY --from=build /app/dist /srv
EXPOSE 80 EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget -qO- http://127.0.0.1:80/health || exit 1 CMD wget -qO- http://127.0.0.1:80/health || exit 1

View File

@ -1,27 +1,27 @@
.PHONY: up down logs rebuild dev prod clean .PHONY: up down logs rebuild dev prod clean
up: up:
docker compose up -d --build docker compose up -d --build
down: down:
docker compose down docker compose down
logs: logs:
docker compose logs -f docker compose logs -f
rebuild: rebuild:
docker compose down docker compose down
docker compose up -d --build docker compose up -d --build
dev: dev:
@sed -i 's/^APP_ENV=.*/APP_ENV=dev/' .env @sed -i 's/^APP_ENV=.*/APP_ENV=dev/' .env
@sed -i 's/^APP_PORT=.*/APP_PORT=4321/' .env @sed -i 's/^APP_PORT=.*/APP_PORT=4321/' .env
$(MAKE) rebuild $(MAKE) rebuild
prod: prod:
@sed -i 's/^APP_ENV=.*/APP_ENV=prod/' .env @sed -i 's/^APP_ENV=.*/APP_ENV=prod/' .env
@sed -i 's/^APP_PORT=.*/APP_PORT=80/' .env @sed -i 's/^APP_PORT=.*/APP_PORT=80/' .env
$(MAKE) rebuild $(MAKE) rebuild
clean: clean:
docker compose down --rmi local -v docker compose down --rmi local -v

View File

@ -1,149 +1,149 @@
import { defineConfig } from 'astro/config'; import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight'; import starlight from '@astrojs/starlight';
import starlightImageZoom from 'starlight-image-zoom'; import starlightImageZoom from 'starlight-image-zoom';
import starlightLinksValidator from 'starlight-links-validator'; import starlightLinksValidator from 'starlight-links-validator';
export default defineConfig({ export default defineConfig({
telemetry: false, telemetry: false,
devToolbar: { devToolbar: {
enabled: false, enabled: false,
}, },
server: { server: {
host: '0.0.0.0', host: '0.0.0.0',
port: 4321, port: 4321,
}, },
vite: { vite: {
server: { server: {
allowedHosts: [process.env.PUBLIC_DOMAIN, 'localhost'].filter(Boolean), allowedHosts: [process.env.PUBLIC_DOMAIN, 'localhost'].filter(Boolean),
...(process.env.VITE_HMR_HOST && { ...(process.env.VITE_HMR_HOST && {
hmr: { hmr: {
host: process.env.VITE_HMR_HOST, host: process.env.VITE_HMR_HOST,
protocol: 'wss', protocol: 'wss',
clientPort: 443, clientPort: 443,
}, },
}), }),
}, },
}, },
integrations: [ integrations: [
starlight({ starlight({
title: 'SkyWalker-1 Docs', title: 'SkyWalker-1 Docs',
description: description:
'Reverse-engineered documentation for the Genpix SkyWalker-1 DVB-S USB 2.0 satellite receiver', 'Reverse-engineered documentation for the Genpix SkyWalker-1 DVB-S USB 2.0 satellite receiver',
plugins: [starlightImageZoom(), starlightLinksValidator()], plugins: [starlightImageZoom(), starlightLinksValidator()],
social: [ social: [
{ {
icon: 'external', icon: 'external',
label: 'Git Repository', label: 'Git Repository',
href: 'https://git.supported.systems/warehack.ing/skywalker-1', href: 'https://git.supported.systems/warehack.ing/skywalker-1',
}, },
], ],
customCss: ['./src/styles/custom.css'], customCss: ['./src/styles/custom.css'],
sidebar: [ sidebar: [
{ {
label: 'Hardware', label: 'Hardware',
items: [ items: [
{ label: 'Overview', slug: 'hardware/overview' }, { label: 'Overview', slug: 'hardware/overview' },
{ label: 'GPIO Pin Map', slug: 'hardware/gpio-pinmap' }, { label: 'GPIO Pin Map', slug: 'hardware/gpio-pinmap' },
{ label: 'RF Specifications', slug: 'hardware/rf-specifications' }, { label: 'RF Specifications', slug: 'hardware/rf-specifications' },
{ label: 'RF Coverage', slug: 'hardware/rf-coverage' }, { label: 'RF Coverage', slug: 'hardware/rf-coverage' },
], ],
}, },
{ {
label: 'USB Interface', label: 'USB Interface',
items: [ items: [
{ label: 'Interface', slug: 'usb/interface' }, { label: 'Interface', slug: 'usb/interface' },
{ label: 'Vendor Commands', slug: 'usb/vendor-commands' }, { label: 'Vendor Commands', slug: 'usb/vendor-commands' },
{ label: 'Boot Sequence', slug: 'usb/boot-sequence' }, { label: 'Boot Sequence', slug: 'usb/boot-sequence' },
{ label: 'Config Status', slug: 'usb/config-status' }, { label: 'Config Status', slug: 'usb/config-status' },
], ],
}, },
{ {
label: 'BCM4500', label: 'BCM4500',
items: [ items: [
{ label: 'Register Map', slug: 'bcm4500/register-map' }, { label: 'Register Map', slug: 'bcm4500/register-map' },
{ label: 'Demodulator', slug: 'bcm4500/demodulator' }, { label: 'Demodulator', slug: 'bcm4500/demodulator' },
{ label: 'Tuning Protocol', slug: 'bcm4500/tuning-protocol' }, { label: 'Tuning Protocol', slug: 'bcm4500/tuning-protocol' },
{ label: 'GPIF Streaming', slug: 'bcm4500/gpif-streaming' }, { label: 'GPIF Streaming', slug: 'bcm4500/gpif-streaming' },
{ label: 'Signal Monitoring', slug: 'bcm4500/signal-monitoring' }, { label: 'Signal Monitoring', slug: 'bcm4500/signal-monitoring' },
], ],
}, },
{ {
label: 'LNB & DiSEqC', label: 'LNB & DiSEqC',
items: [ items: [
{ label: 'LNB Control', slug: 'lnb-diseqc/lnb-control' }, { label: 'LNB Control', slug: 'lnb-diseqc/lnb-control' },
{ label: 'DiSEqC Protocol', slug: 'lnb-diseqc/diseqc-protocol' }, { label: 'DiSEqC Protocol', slug: 'lnb-diseqc/diseqc-protocol' },
{ label: 'Legacy Switch', slug: 'lnb-diseqc/legacy-switch' }, { label: 'Legacy Switch', slug: 'lnb-diseqc/legacy-switch' },
], ],
}, },
{ {
label: 'I\u00B2C Bus', label: 'I\u00B2C Bus',
items: [ items: [
{ label: 'Bus Architecture', slug: 'i2c/bus-architecture' }, { label: 'Bus Architecture', slug: 'i2c/bus-architecture' },
{ {
label: 'STOP Corruption Bug', label: 'STOP Corruption Bug',
slug: 'i2c/stop-corruption-bug', slug: 'i2c/stop-corruption-bug',
}, },
], ],
}, },
{ {
label: 'Firmware', label: 'Firmware',
items: [ items: [
{ {
label: 'Version Comparison', label: 'Version Comparison',
slug: 'firmware/version-comparison', slug: 'firmware/version-comparison',
}, },
{ label: 'Rev.2 Analysis', slug: 'firmware/rev2-analysis' }, { label: 'Rev.2 Analysis', slug: 'firmware/rev2-analysis' },
{ label: 'Kernel FW01', slug: 'firmware/kernel-fw01' }, { label: 'Kernel FW01', slug: 'firmware/kernel-fw01' },
{ label: 'FW2.13 Variants', slug: 'firmware/fw213-variants' }, { label: 'FW2.13 Variants', slug: 'firmware/fw213-variants' },
{ label: 'Custom v3.01', slug: 'firmware/custom-v301' }, { label: 'Custom v3.01', slug: 'firmware/custom-v301' },
{ label: 'Custom v3.02', slug: 'firmware/custom-v302' }, { label: 'Custom v3.02', slug: 'firmware/custom-v302' },
{ label: 'Custom v3.05', slug: 'firmware/custom-v305' }, { label: 'Custom v3.05', slug: 'firmware/custom-v305' },
{ label: 'Storage Formats', slug: 'firmware/storage-formats' }, { label: 'Storage Formats', slug: 'firmware/storage-formats' },
], ],
}, },
{ {
label: 'Driver', label: 'Driver',
items: [ items: [
{ label: 'Linux Kernel', slug: 'driver/linux-kernel' }, { label: 'Linux Kernel', slug: 'driver/linux-kernel' },
{ label: 'DVB-S2', slug: 'driver/dvb-s2' }, { label: 'DVB-S2', slug: 'driver/dvb-s2' },
], ],
}, },
{ {
label: 'Tools', label: 'Tools',
items: [ items: [
{ label: 'Firmware Loader', slug: 'tools/firmware-loader' }, { label: 'Firmware Loader', slug: 'tools/firmware-loader' },
{ label: 'Tuning', slug: 'tools/tuning' }, { label: 'Tuning', slug: 'tools/tuning' },
{ label: 'SkyWalker RF Tool', slug: 'tools/skywalker' }, { label: 'SkyWalker RF Tool', slug: 'tools/skywalker' },
{ label: 'SkyWalker TUI', slug: 'tools/tui' }, { label: 'SkyWalker TUI', slug: 'tools/tui' },
{ label: 'Motor Control', slug: 'tools/motor' }, { label: 'Motor Control', slug: 'tools/motor' },
{ label: 'Carrier Survey', slug: 'tools/survey' }, { label: 'Carrier Survey', slug: 'tools/survey' },
{ label: 'EEPROM Utilities', slug: 'tools/eeprom-utilities' }, { label: 'EEPROM Utilities', slug: 'tools/eeprom-utilities' },
{ label: 'Debugging', slug: 'tools/debugging' }, { label: 'Debugging', slug: 'tools/debugging' },
{ label: 'TS Analyzer', slug: 'tools/ts-analyzer' }, { label: 'TS Analyzer', slug: 'tools/ts-analyzer' },
{ label: 'Spectrum Analysis', slug: 'tools/spectrum-analysis' }, { label: 'Spectrum Analysis', slug: 'tools/spectrum-analysis' },
{ label: 'Hydrogen 21 cm', slug: 'tools/h21cm' }, { label: 'Hydrogen 21 cm', slug: 'tools/h21cm' },
{ label: 'RF Test Bench', slug: 'tools/rf-testbench' }, { label: 'RF Test Bench', slug: 'tools/rf-testbench' },
{ label: 'Beacon Logger', slug: 'tools/beacon-logger' }, { label: 'Beacon Logger', slug: 'tools/beacon-logger' },
{ label: 'Arc Survey', slug: 'tools/arc-survey' }, { label: 'Arc Survey', slug: 'tools/arc-survey' },
{ label: 'MCP Server', slug: 'tools/mcp-server' }, { label: 'MCP Server', slug: 'tools/mcp-server' },
{ label: 'Safety Testing', slug: 'tools/safety-testing' }, { label: 'Safety Testing', slug: 'tools/safety-testing' },
], ],
}, },
{ {
label: 'Guides', label: 'Guides',
items: [ items: [
{ label: 'Applications & Use Cases', slug: 'guides/applications' }, { label: 'Applications & Use Cases', slug: 'guides/applications' },
{ label: 'QO-100 DATV Reception', slug: 'guides/qo100-datv' }, { label: 'QO-100 DATV Reception', slug: 'guides/qo100-datv' },
{ label: "Experimenter's Roadmap", slug: 'guides/experimenter-roadmap' }, { label: "Experimenter's Roadmap", slug: 'guides/experimenter-roadmap' },
], ],
}, },
{ {
label: 'Reference', label: 'Reference',
items: [ items: [
{ label: 'Sources', slug: 'reference/master-reference' }, { label: 'Sources', slug: 'reference/master-reference' },
], ],
}, },
], ],
}), }),
], ],
}); });

View File

@ -1,31 +1,31 @@
services: services:
docs: docs:
build: build:
context: . context: .
target: ${APP_ENV:-dev} target: ${APP_ENV:-dev}
container_name: skywalker-1-docs container_name: skywalker-1-docs
restart: unless-stopped restart: unless-stopped
environment: environment:
- PUBLIC_DOMAIN=${PUBLIC_DOMAIN} - PUBLIC_DOMAIN=${PUBLIC_DOMAIN}
- VITE_HMR_HOST=${VITE_HMR_HOST} - VITE_HMR_HOST=${VITE_HMR_HOST}
networks: networks:
- caddy - caddy
labels: labels:
caddy: ${PUBLIC_DOMAIN} caddy: ${PUBLIC_DOMAIN}
caddy.reverse_proxy: "{{upstreams ${APP_PORT:-4321}}}" caddy.reverse_proxy: "{{upstreams ${APP_PORT:-4321}}}"
caddy.reverse_proxy.flush_interval: "-1" caddy.reverse_proxy.flush_interval: "-1"
caddy.reverse_proxy.transport: http caddy.reverse_proxy.transport: http
caddy.reverse_proxy.transport.read_timeout: "0" caddy.reverse_proxy.transport.read_timeout: "0"
caddy.reverse_proxy.transport.write_timeout: "0" caddy.reverse_proxy.transport.write_timeout: "0"
caddy.reverse_proxy.transport.keepalive: 5m caddy.reverse_proxy.transport.keepalive: 5m
caddy.reverse_proxy.transport.keepalive_idle_conns: "10" caddy.reverse_proxy.transport.keepalive_idle_conns: "10"
caddy.reverse_proxy.stream_timeout: 24h caddy.reverse_proxy.stream_timeout: 24h
caddy.reverse_proxy.stream_close_delay: 5s caddy.reverse_proxy.stream_close_delay: 5s
volumes: volumes:
- ./src:/app/src - ./src:/app/src
- ./public:/app/public - ./public:/app/public
- ./astro.config.mjs:/app/astro.config.mjs - ./astro.config.mjs:/app/astro.config.mjs
networks: networks:
caddy: caddy:
external: true external: true

14930
site/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,19 @@
{ {
"name": "skywalker-1-docs", "name": "skywalker-1-docs",
"type": "module", "type": "module",
"version": "0.0.1", "version": "0.0.1",
"scripts": { "scripts": {
"dev": "astro dev", "dev": "astro dev",
"start": "astro dev", "start": "astro dev",
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"astro": "^5.17.2", "astro": "^5.17.2",
"@astrojs/starlight": "^0.37.6", "@astrojs/starlight": "^0.37.6",
"sharp": "^0.33.0", "sharp": "^0.33.0",
"starlight-image-zoom": "^0.13.2", "starlight-image-zoom": "^0.13.2",
"starlight-links-validator": "^0.19.2" "starlight-links-validator": "^0.19.2"
} }
} }

View File

@ -1,6 +1,6 @@
import { defineCollection } from 'astro:content'; import { defineCollection } from 'astro:content';
import { docsSchema } from '@astrojs/starlight/schema'; import { docsSchema } from '@astrojs/starlight/schema';
export const collections = { export const collections = {
docs: defineCollection({ schema: docsSchema() }), docs: defineCollection({ schema: docsSchema() }),
}; };

View File

@ -1,230 +1,230 @@
--- ---
title: BCM4500 Demodulator Interface title: BCM4500 Demodulator Interface
description: Broadcom BCM4500 I2C addressing, register access protocol, and indirect register programming. description: Broadcom BCM4500 I2C addressing, register access protocol, and indirect register programming.
--- ---
import { Tabs, TabItem, Badge, Aside, Steps } from '@astrojs/starlight/components'; import { Tabs, TabItem, Badge, Aside, Steps } from '@astrojs/starlight/components';
The Broadcom BCM4500 is a 128-pin MQFP satellite demodulator that handles RF demodulation, forward error correction, and MPEG-2 transport stream output. The FX2 communicates with it exclusively over the shared I2C bus using an indirect register protocol. The Broadcom BCM4500 is a 128-pin MQFP satellite demodulator that handles RF demodulation, forward error correction, and MPEG-2 transport stream output. The FX2 communicates with it exclusively over the shared I2C bus using an indirect register protocol.
See the [Register Map](/bcm4500/register-map/) for a consolidated lookup of all BCM4500 and FX2 register addresses referenced on this page. See the [Register Map](/bcm4500/register-map/) for a consolidated lookup of all BCM4500 and FX2 register addresses referenced on this page.
## I2C Addressing ## I2C Addressing
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| 7-bit I2C address | 0x08 | | 7-bit I2C address | 0x08 |
| 8-bit write address | 0x10 | | 8-bit write address | 0x10 |
| 8-bit read address | 0x11 | | 8-bit read address | 0x11 |
| Bus speed | 400 kHz | | Bus speed | 400 kHz |
| FX2 I2C controller registers | I2CS (0xE678), I2DAT (0xE679), I2CTL (0xE67A) | | FX2 I2C controller registers | I2CS (0xE678), I2DAT (0xE679), I2CTL (0xE67A) |
| Alternate probe addresses (v2.13) | 0x3F, 0x7F | | Alternate probe addresses (v2.13) | 0x3F, 0x7F |
The custom firmware and kernel driver use the 7-bit address 0x08. The stock firmware writes `addr << 1` = 0x10 for write and `(addr << 1) | 1` = 0x11 for read, following standard I2C convention. The custom firmware and kernel driver use the 7-bit address 0x08. The stock firmware writes `addr << 1` = 0x10 for write and `(addr << 1) | 1` = 0x11 for read, following standard I2C convention.
<Aside type="note" title="Alternate Addresses"> <Aside type="note" title="Alternate Addresses">
The v2.13 firmware probes I2C addresses 0x7F and 0x3F at startup (INT0 handler) to detect which demodulator variant is present. These may be alternative I2C address configurations or addresses for different demodulator sub-systems on hardware variants. The v2.13 firmware probes I2C addresses 0x7F and 0x3F at startup (INT0 handler) to detect which demodulator variant is present. These may be alternative I2C address configurations or addresses for different demodulator sub-systems on hardware variants.
</Aside> </Aside>
## Direct Registers ## Direct Registers
These registers are accessed via standard I2C write/read to the BCM4500's device address: These registers are accessed via standard I2C write/read to the BCM4500's device address:
| Register | Function | Used By | | Register | Function | Used By |
|----------|----------|---------| |----------|----------|---------|
| 0xA2 | Status register (polled for readiness during boot) | Boot probe, signal strength | | 0xA2 | Status register (polled for readiness during boot) | Boot probe, signal strength |
| 0xA4 | Lock/ready register; bit 5 (0x20) = signal locked | Signal lock check | | 0xA4 | Lock/ready register; bit 5 (0x20) = signal locked | Signal lock check |
| 0xA6 | Indirect page/address select | Indirect register protocol | | 0xA6 | Indirect page/address select | Indirect register protocol |
| 0xA7 | Indirect data register (read/write) | Indirect register protocol | | 0xA7 | Indirect data register (read/write) | Indirect register protocol |
| 0xA8 | Indirect command register | Indirect register protocol | | 0xA8 | Indirect command register | Indirect register protocol |
| 0xF9 | Demod status (v2.13 only) | GET_DEMOD_STATUS (0x99) / INT0 polling | | 0xF9 | Demod status (v2.13 only) | GET_DEMOD_STATUS (0x99) / INT0 polling |
## Indirect Register Protocol ## Indirect Register Protocol
The BCM4500 uses an indirect register access scheme through three directly-addressable registers (0xA6, 0xA7, 0xA8). All tuning configuration, initialization data, and signal monitoring are performed through this protocol. The BCM4500 uses an indirect register access scheme through three directly-addressable registers (0xA6, 0xA7, 0xA8). All tuning configuration, initialization data, and signal monitoring are performed through this protocol.
### Indirect Write Sequence ### Indirect Write Sequence
<Steps> <Steps>
1. **Page select** -- I2C WRITE to 0x08, register 0xA6 with the page number (typically 0x00). 1. **Page select** -- I2C WRITE to 0x08, register 0xA6 with the page number (typically 0x00).
2. **Data write** -- I2C WRITE to 0x08, register 0xA7 with N data bytes. The auto-increment feature allows writing multiple bytes in a single I2C transaction. 2. **Data write** -- I2C WRITE to 0x08, register 0xA7 with N data bytes. The auto-increment feature allows writing multiple bytes in a single I2C transaction.
3. **Execute** -- I2C WRITE to 0x08, register 0xA8 with value 0x03 (indirect write command). 3. **Execute** -- I2C WRITE to 0x08, register 0xA8 with value 0x03 (indirect write command).
4. **Poll completion** -- I2C READ register 0xA8 until bit 0 clears (command complete). 4. **Poll completion** -- I2C READ register 0xA8 until bit 0 clears (command complete).
5. **Verify** -- Optionally I2C READ register 0xA7 to read back and compare. 5. **Verify** -- Optionally I2C READ register 0xA7 to read back and compare.
</Steps> </Steps>
```c title="Indirect Write Protocol" ```c title="Indirect Write Protocol"
// Step 1: Page select // Step 1: Page select
I2C WRITE: [START] [0x10] [0xA6] [0x00] [STOP] I2C WRITE: [START] [0x10] [0xA6] [0x00] [STOP]
// Step 2: Data write (multi-byte, auto-increment) // Step 2: Data write (multi-byte, auto-increment)
I2C WRITE: [START] [0x10] [0xA7] [data0] [data1] ... [dataN] [STOP] I2C WRITE: [START] [0x10] [0xA7] [data0] [data1] ... [dataN] [STOP]
// Step 3: Execute indirect write // Step 3: Execute indirect write
I2C WRITE: [START] [0x10] [0xA8] [0x03] [STOP] I2C WRITE: [START] [0x10] [0xA8] [0x03] [STOP]
// Step 4: Poll until complete // Step 4: Poll until complete
I2C READ: [START] [0x10] [0xA8] [Sr] [0x11] [result] [STOP] I2C READ: [START] [0x10] [0xA8] [Sr] [0x11] [result] [STOP]
// Repeat until (result & 0x01) == 0 // Repeat until (result & 0x01) == 0
``` ```
### Indirect Read Sequence ### Indirect Read Sequence
<Steps> <Steps>
1. **Address select** -- I2C WRITE to 0x08, register 0xA6 with the target register address. 1. **Address select** -- I2C WRITE to 0x08, register 0xA6 with the target register address.
2. **Placeholder write** -- I2C WRITE to 0x08, register 0xA7 with value 0x00. 2. **Placeholder write** -- I2C WRITE to 0x08, register 0xA7 with value 0x00.
3. **Execute** -- I2C WRITE to 0x08, register 0xA8 with value 0x01 (indirect read command). 3. **Execute** -- I2C WRITE to 0x08, register 0xA8 with value 0x01 (indirect read command).
4. **Wait** -- Short delay (~1 ms) for the BCM4500 to fetch the data. 4. **Wait** -- Short delay (~1 ms) for the BCM4500 to fetch the data.
5. **Read result** -- I2C READ from 0x08, register 0xA7 to get the result byte. 5. **Read result** -- I2C READ from 0x08, register 0xA7 to get the result byte.
</Steps> </Steps>
### Auto-Increment Behavior ### Auto-Increment Behavior
The BCM4500's data register (0xA7) supports auto-increment for multi-byte writes within a single I2C transaction. When writing N data bytes to 0xA7 without issuing STOP between bytes, the BCM4500 internally advances its data buffer pointer: The BCM4500's data register (0xA7) supports auto-increment for multi-byte writes within a single I2C transaction. When writing N data bytes to 0xA7 without issuing STOP between bytes, the BCM4500 internally advances its data buffer pointer:
``` ```
I2C transaction (single write, multiple data bytes): I2C transaction (single write, multiple data bytes):
START -> 0x10 (write) -> 0xA7 (reg) -> data[0] -> data[1] -> ... -> data[N-1] -> STOP START -> 0x10 (write) -> 0xA7 (reg) -> data[0] -> data[1] -> ... -> data[N-1] -> STOP
``` ```
The firmware uses this for initialization blocks and tuning data, reducing I2C bus overhead compared to byte-by-byte writes. The firmware uses this for initialization blocks and tuning data, reducing I2C bus overhead compared to byte-by-byte writes.
### Stock Firmware Init Block Write Pattern ### Stock Firmware Init Block Write Pattern
The stock firmware uses a specific pattern for writing initialization blocks, extracted from `FUN_CODE_0ddd`: The stock firmware uses a specific pattern for writing initialization blocks, extracted from `FUN_CODE_0ddd`:
```c title="Init Block Write Sequence" ```c title="Init Block Write Sequence"
// 1. Page select = 0 // 1. Page select = 0
I2C WRITE: [0x10] [0xA6] [0x00] I2C WRITE: [0x10] [0xA6] [0x00]
// 2. Multi-byte data (auto-increment) // 2. Multi-byte data (auto-increment)
I2C WRITE: [0x10] [0xA7] [data0] [data1] ... [dataN] I2C WRITE: [0x10] [0xA7] [data0] [data1] ... [dataN]
// 3. Trailing zero (stock firmware quirk) // 3. Trailing zero (stock firmware quirk)
I2C WRITE: [0x10] [0xA7] [0x00] I2C WRITE: [0x10] [0xA7] [0x00]
// 4. Commit indirect write // 4. Commit indirect write
I2C WRITE: [0x10] [0xA8] [0x03] I2C WRITE: [0x10] [0xA8] [0x03]
// 5. Poll for completion // 5. Poll for completion
I2C READ: [0xA8] until bit 0 clear I2C READ: [0xA8] until bit 0 clear
``` ```
<Aside type="note" title="Trailing Zero"> <Aside type="note" title="Trailing Zero">
The trailing zero write (step 3) appears in all stock firmware versions. Its purpose is unclear -- it may zero-pad the data buffer or serve as an end-of-data marker within the BCM4500's indirect register engine. The trailing zero write (step 3) appears in all stock firmware versions. Its purpose is unclear -- it may zero-pad the data buffer or serve as an end-of-data marker within the BCM4500's indirect register engine.
</Aside> </Aside>
## Demodulator Scan ## Demodulator Scan
### Tuning Retry (All Firmware Versions) ### Tuning Retry (All Firmware Versions)
The tune function wraps the BCM4500 I2C programming sequence in a two-level retry loop: The tune function wraps the BCM4500 I2C programming sequence in a two-level retry loop:
- **Inner loop**: tries up to 3 different I2C address configurations per attempt. This supports hardware variants where the BCM4500 may appear at different bus addresses. - **Inner loop**: tries up to 3 different I2C address configurations per attempt. This supports hardware variants where the BCM4500 may appear at different bus addresses.
- **Outer loop**: retries the entire inner scan up to 3 times. - **Outer loop**: retries the entire inner scan up to 3 times.
This yields up to **3 &times; 3 = 9 total I2C programming attempts** per tune command. The v2.13 firmware adds a 20-attempt retry with checksum verification on each individual I2C write within the programming step. This yields up to **3 &times; 3 = 9 total I2C programming attempts** per tune command. The v2.13 firmware adds a 20-attempt retry with checksum verification on each individual I2C write within the programming step.
### Boot-Time Probe (v2.13 Only) ### Boot-Time Probe (v2.13 Only)
The v2.13 firmware repurposed the INT0 interrupt handler (vector at `CODE:0003`) from USB re-enumeration to demodulator availability detection. The handler runs once during boot, before the main loop: The v2.13 firmware repurposed the INT0 interrupt handler (vector at `CODE:0003`) from USB re-enumeration to demodulator availability detection. The handler runs once during boot, before the main loop:
```c title="INT0 handler (v2.13) — demod probe" ```c title="INT0 handler (v2.13) — demod probe"
void INT0_vector(void) { void INT0_vector(void) {
for (counter = 0x28; counter != 0; counter--) { // 40 iterations for (counter = 0x28; counter != 0; counter--) { // 40 iterations
byte result = I2C_read(0x7F); // Probe first alternate address byte result = I2C_read(0x7F); // Probe first alternate address
if (result != 0x01) { if (result != 0x01) {
result = I2C_read(0x3F); // Probe second alternate address result = I2C_read(0x3F); // Probe second alternate address
if (result != 0x01) break; // Got a response — demod present if (result != 0x01) break; // Got a response — demod present
} }
} }
no_demod_flag = (counter == 0); // True if all 40 attempts failed no_demod_flag = (counter == 0); // True if all 40 attempts failed
} }
``` ```
If neither address responds after 40 iterations, `no_demod_flag` is set. This flag causes the firmware to skip all tuning attempts, avoiding I2C bus hangs on boards where the demodulator is absent or unpopulated. If neither address responds after 40 iterations, `no_demod_flag` is set. This flag causes the firmware to skip all tuning attempts, avoiding I2C bus hangs on boards where the demodulator is absent or unpopulated.
<Aside type="note" title="Probe vs. Operating Address"> <Aside type="note" title="Probe vs. Operating Address">
The probe addresses (0x7F and 0x3F) are **not** the normal operating address. During regular tuning and signal monitoring, the BCM4500 is always accessed at its standard 7-bit address **0x08**. The probe addresses may be factory-default or configuration-pin-selected addresses that the BCM4500 responds to before its I2C address is programmed, or they may belong to different sub-systems on the demodulator IC. See the [Register Map &mdash; I2C Bus Addresses](/bcm4500/register-map/#i2c-bus-addresses) for the full address table. The probe addresses (0x7F and 0x3F) are **not** the normal operating address. During regular tuning and signal monitoring, the BCM4500 is always accessed at its standard 7-bit address **0x08**. The probe addresses may be factory-default or configuration-pin-selected addresses that the BCM4500 responds to before its I2C address is programmed, or they may belong to different sub-systems on the demodulator IC. See the [Register Map &mdash; I2C Bus Addresses](/bcm4500/register-map/#i2c-bus-addresses) for the full address table.
</Aside> </Aside>
### `no_demod_flag` Behavior ### `no_demod_flag` Behavior
When the boot probe fails (all 40 attempts exhausted): When the boot probe fails (all 40 attempts exhausted):
1. `no_demod_flag` is set to a non-zero value 1. `no_demod_flag` is set to a non-zero value
2. The firmware enters its normal main loop but skips BCM4500 initialization 2. The firmware enters its normal main loop but skips BCM4500 initialization
3. `TUNE_8PSK` (0x86) commands are accepted but silently fail (no I2C transactions issued) 3. `TUNE_8PSK` (0x86) commands are accepted but silently fail (no I2C transactions issued)
4. `GET_SIGNAL_LOCK` (0x90) returns 0x00 (unlocked) 4. `GET_SIGNAL_LOCK` (0x90) returns 0x00 (unlocked)
5. The device remains functional for USB communication but cannot tune 5. The device remains functional for USB communication but cannot tune
This graceful degradation allows the host software to detect the condition via persistent lock failure rather than USB timeouts. This graceful degradation allows the host software to detect the condition via persistent lock failure rather than USB timeouts.
## FEC Architecture ## FEC Architecture
The BCM4500 contains two FEC decoder paths: The BCM4500 contains two FEC decoder paths:
<Tabs> <Tabs>
<TabItem label="Turbo FEC"> <TabItem label="Turbo FEC">
**Advanced Modulation Turbo FEC Decoder** **Advanced Modulation Turbo FEC Decoder**
Iterative turbo code decoder with the following code rates: Iterative turbo code decoder with the following code rates:
| Modulation | Supported Rates | | Modulation | Supported Rates |
|-----------|----------------| |-----------|----------------|
| QPSK | 1/4, 1/2, 3/4 | | QPSK | 1/4, 1/2, 3/4 |
| 8PSK | 2/3, 3/4, 5/6, 8/9 | | 8PSK | 2/3, 3/4, 5/6, 8/9 |
| 16QAM | 3/4 | | 16QAM | 3/4 |
Outer code: Reed-Solomon (t=10). Outer code: Reed-Solomon (t=10).
These turbo codes are Broadcom/EchoStar proprietary and are not part of any open standard. They were used by Dish Network for high-definition satellite broadcasts. These turbo codes are Broadcom/EchoStar proprietary and are not part of any open standard. They were used by Dish Network for high-definition satellite broadcasts.
</TabItem> </TabItem>
<TabItem label="Legacy FEC"> <TabItem label="Legacy FEC">
**Legacy DVB/DIRECTV/DCII-Compliant FEC Decoder** **Legacy DVB/DIRECTV/DCII-Compliant FEC Decoder**
Concatenated decoder with: Concatenated decoder with:
| Stage | Type | Rates | | Stage | Type | Rates |
|-------|------|-------| |-------|------|-------|
| Inner | Viterbi (convolutional code) | 1/2, 2/3, 3/4, 5/6, 7/8 | | Inner | Viterbi (convolutional code) | 1/2, 2/3, 3/4, 5/6, 7/8 |
| Outer | Reed-Solomon | Standard DVB-S parameters | | Outer | Reed-Solomon | Standard DVB-S parameters |
This decoder handles standard DVB-S QPSK, DVB-S BPSK, DSS QPSK, and all Digicipher II modes. This decoder handles standard DVB-S QPSK, DVB-S BPSK, DSS QPSK, and all Digicipher II modes.
</TabItem> </TabItem>
</Tabs> </Tabs>
<Aside type="caution" title="No DVB-S2 Support"> <Aside type="caution" title="No DVB-S2 Support">
There is no LDPC or BCH decoder hardware in the BCM4500. DVB-S2 requires both of these, making it physically impossible to add DVB-S2 support through firmware updates. There is no LDPC or BCH decoder hardware in the BCM4500. DVB-S2 requires both of these, making it physically impossible to add DVB-S2 support through firmware updates.
</Aside> </Aside>
## Modulation Mode Constants ## Modulation Mode Constants
The firmware uses a 10-entry dispatch table for modulation types. See [Tuning Protocol](/bcm4500/tuning-protocol/) for the full tuning sequence. The firmware uses a 10-entry dispatch table for modulation types. See [Tuning Protocol](/bcm4500/tuning-protocol/) for the full tuning sequence.
| Index | Modulation | FEC Path | | Index | Modulation | FEC Path |
|-------|-----------|----------| |-------|-----------|----------|
| 0 | DVB-S QPSK | Legacy (Viterbi + RS) | | 0 | DVB-S QPSK | Legacy (Viterbi + RS) |
| 1 | Turbo QPSK | Turbo | | 1 | Turbo QPSK | Turbo |
| 2 | Turbo 8PSK | Turbo | | 2 | Turbo 8PSK | Turbo |
| 3 | Turbo 16QAM | Turbo | | 3 | Turbo 16QAM | Turbo |
| 4 | DCII Combo | Legacy | | 4 | DCII Combo | Legacy |
| 5 | DCII I-stream | Legacy | | 5 | DCII I-stream | Legacy |
| 6 | DCII Q-stream | Legacy | | 6 | DCII Q-stream | Legacy |
| 7 | DCII Offset QPSK | Legacy | | 7 | DCII Offset QPSK | Legacy |
| 8 | DSS QPSK | Legacy (Viterbi + RS) | | 8 | DSS QPSK | Legacy (Viterbi + RS) |
| 9 | DVB-S BPSK | Legacy (Viterbi + RS) | | 9 | DVB-S BPSK | Legacy (Viterbi + RS) |
Indices 8 and 9 (DSS and DVB BPSK) share the same firmware handler. The FEC lookup uses the same table as DVB-S QPSK but ORs the result with 0x80 to distinguish them. Indices 8 and 9 (DSS and DVB BPSK) share the same firmware handler. The FEC lookup uses the same table as DVB-S QPSK but ORs the result with 0x80 to distinguish them.

View File

@ -1,241 +1,241 @@
--- ---
title: GPIF Streaming title: GPIF Streaming
description: GPIF engine configuration, waveform descriptors, and transport stream data path from BCM4500 to USB host. description: GPIF engine configuration, waveform descriptors, and transport stream data path from BCM4500 to USB host.
--- ---
import { Tabs, TabItem, Badge, Aside, Steps } from '@astrojs/starlight/components'; import { Tabs, TabItem, Badge, Aside, Steps } from '@astrojs/starlight/components';
The GPIF (General Programmable Interface) engine in the Cypress FX2 provides a hardware-managed data path from the BCM4500 demodulator to the USB host. After initial setup, no firmware intervention occurs in the data path -- the GPIF engine reads transport stream data directly into the EP2 FIFO, and the AUTOIN mechanism automatically commits full packets to the USB controller. The GPIF (General Programmable Interface) engine in the Cypress FX2 provides a hardware-managed data path from the BCM4500 demodulator to the USB host. After initial setup, no firmware intervention occurs in the data path -- the GPIF engine reads transport stream data directly into the EP2 FIFO, and the AUTOIN mechanism automatically commits full packets to the USB controller.
## Data Flow Architecture ## Data Flow Architecture
``` ```
Cypress FX2 (CY7C68013A) Cypress FX2 (CY7C68013A)
+-----------------------------+ +-----------------------------+
| | | |
BCM4500 P3.5 TS_EN | GPIF Engine EP2 FIFO | USB 2.0 HS BCM4500 P3.5 TS_EN | GPIF Engine EP2 FIFO | USB 2.0 HS
Demodulator <-----------------+ (Master Read) (AUTOIN) +------------> Host Demodulator <-----------------+ (Master Read) (AUTOIN) +------------> Host
(I2C:0x08) GPIF Data Bus | 0xE4xx wfm 4x buf | EP2 (0x82) (I2C:0x08) GPIF Data Bus | 0xE4xx wfm 4x buf | EP2 (0x82)
-------------------> CTL/RDY pins 8-bit | Bulk IN -------------------> CTL/RDY pins 8-bit | Bulk IN
8-bit parallel TS | | 7 URBs x 8KB 8-bit parallel TS | | 7 URBs x 8KB
+-----------------------------+ +-----------------------------+
``` ```
<Aside type="note" title="Zero-Copy Path"> <Aside type="note" title="Zero-Copy Path">
The data path is fully hardware-managed. The GPIF engine reads data directly into the EP2 FIFO buffer. The EP2FIFOCFG AUTOIN bit causes the hardware to automatically commit full packets to the USB controller for transfer to the host. The FLOWSTATE engine re-triggers GPIF transactions when buffer space becomes available. The firmware only needs to start/stop the GPIF engine. The data path is fully hardware-managed. The GPIF engine reads data directly into the EP2 FIFO buffer. The EP2FIFOCFG AUTOIN bit causes the hardware to automatically commit full packets to the USB controller for transfer to the host. The FLOWSTATE engine re-triggers GPIF transactions when buffer space becomes available. The firmware only needs to start/stop the GPIF engine.
</Aside> </Aside>
## Key Register Configuration ## Key Register Configuration
All values are identical across the three stock firmware versions (v2.06, Rev.2 v2.10, v2.13): All values are identical across the three stock firmware versions (v2.06, Rev.2 v2.10, v2.13):
| Register | Address | Value | Function | | Register | Address | Value | Function |
|----------|---------|-------|----------| |----------|---------|-------|----------|
| IFCONFIG | 0xE601 | 0xEE | Internal 48 MHz clock, GPIF master, async, debug output | | IFCONFIG | 0xE601 | 0xEE | Internal 48 MHz clock, GPIF master, async, debug output |
| EP2FIFOCFG | 0xE618 | 0x0C | AUTOIN=1, ZEROLENIN=1, 8-bit data path | | EP2FIFOCFG | 0xE618 | 0x0C | AUTOIN=1, ZEROLENIN=1, 8-bit data path |
| REVCTL | 0xE60B | 0x03 | NOAUTOARM + SKIPCOMMIT | | REVCTL | 0xE60B | 0x03 | NOAUTOARM + SKIPCOMMIT |
| CPUCS | 0xE600 | bits [4:3]=10 | 48 MHz CPU clock | | CPUCS | 0xE600 | bits [4:3]=10 | 48 MHz CPU clock |
| FLOWSTATEA | 0xE668 | OR 0x09 | FSEN (flow state enable) + FS[3] | | FLOWSTATEA | 0xE668 | OR 0x09 | FSEN (flow state enable) + FS[3] |
| GPIFIE | 0xE65C | OR 0x3D | Waveform, TC, DONE, FIFO flag, WF2 interrupts | | GPIFIE | 0xE65C | OR 0x3D | Waveform, TC, DONE, FIFO flag, WF2 interrupts |
### IFCONFIG Decode (0xEE = 1110_1110) ### IFCONFIG Decode (0xEE = 1110_1110)
| Bit | Name | Value | Meaning | | Bit | Name | Value | Meaning |
|-----|------|-------|---------| |-----|------|-------|---------|
| 7 | IFCLKSRC | 1 | Internal clock source | | 7 | IFCLKSRC | 1 | Internal clock source |
| 6 | 3048MHZ | 1 | 48 MHz IFCLK frequency | | 6 | 3048MHZ | 1 | 48 MHz IFCLK frequency |
| 5 | IFCLKOE | 1 | IFCLK pin drives output (clock to BCM4500) | | 5 | IFCLKOE | 1 | IFCLK pin drives output (clock to BCM4500) |
| 4 | IFCLKPOL | 0 | Non-inverted clock polarity | | 4 | IFCLKPOL | 0 | Non-inverted clock polarity |
| 3 | ASYNC | 1 | Asynchronous GPIF (RDY pin handshaking) | | 3 | ASYNC | 1 | Asynchronous GPIF (RDY pin handshaking) |
| 2 | GSTATE | 1 | Debug state output on PORTE | | 2 | GSTATE | 1 | Debug state output on PORTE |
| 1:0 | IFCFG | 10 | GPIF internal master mode | | 1:0 | IFCFG | 10 | GPIF internal master mode |
The FX2 operates as a GPIF master, reading data from the BCM4500's parallel transport stream output. Asynchronous mode means the GPIF uses RDY pin handshaking rather than clock-edge sampling. The FX2 operates as a GPIF master, reading data from the BCM4500's parallel transport stream output. Asynchronous mode means the GPIF uses RDY pin handshaking rather than clock-edge sampling.
### EP2FIFOCFG Decode (0x0C = 0000_1100) ### EP2FIFOCFG Decode (0x0C = 0000_1100)
| Bit | Name | Value | Meaning | | Bit | Name | Value | Meaning |
|-----|------|-------|---------| |-----|------|-------|---------|
| 4 | INFM1 | 0 | Packet count not decremented | | 4 | INFM1 | 0 | Packet count not decremented |
| 3 | AUTOIN | 1 | Auto-commit IN packets when FIFO buffer full | | 3 | AUTOIN | 1 | Auto-commit IN packets when FIFO buffer full |
| 2 | ZEROLENIN | 1 | Allow zero-length IN packets | | 2 | ZEROLENIN | 1 | Allow zero-length IN packets |
| 1 | (reserved) | 0 | -- | | 1 | (reserved) | 0 | -- |
| 0 | WORDWIDE | 0 | 8-bit data path (not 16-bit) | | 0 | WORDWIDE | 0 | 8-bit data path (not 16-bit) |
The AUTOIN bit is critical: when the GPIF fills an EP2 FIFO buffer to the configured packet size, the FX2 hardware automatically arms the buffer for USB transfer. The AUTOIN bit is critical: when the GPIF fills an EP2 FIFO buffer to the configured packet size, the FX2 hardware automatically arms the buffer for USB transfer.
## GPIF Waveform Configuration ## GPIF Waveform Configuration
The GPIF waveform descriptors occupy 128 bytes at 0xE400-0xE47F and are loaded from a compressed init table during firmware startup. The waveform programs a straightforward read cycle: The GPIF waveform descriptors occupy 128 bytes at 0xE400-0xE47F and are loaded from a compressed init table during firmware startup. The waveform programs a straightforward read cycle:
``` ```
States 0-5: CTL outputs = 0x01 (control line asserted), 1 IFCLK each States 0-5: CTL outputs = 0x01 (control line asserted), 1 IFCLK each
State 6: CTL = 0x07, length = 0 (idle/terminate) State 6: CTL = 0x07, length = 0 (idle/terminate)
Opcode: 0x00 (SDP = sample data point) Opcode: 0x00 (SDP = sample data point)
Output: 0xF0 (FIFO write flags) Output: 0xF0 (FIFO write flags)
``` ```
This encodes a simple "assert read strobe, capture data, de-assert" cycle that reads one byte per GPIF transaction from the BCM4500's parallel port into the EP2 FIFO. This encodes a simple "assert read strobe, capture data, de-assert" cycle that reads one byte per GPIF transaction from the BCM4500's parallel port into the EP2 FIFO.
## FIFO Reset Sequence ## FIFO Reset Sequence
All endpoint FIFOs are reset during initialization using the Cypress-prescribed procedure: All endpoint FIFOs are reset during initialization using the Cypress-prescribed procedure:
```c title="FIFO Reset (FUN_CODE_10d9)" ```c title="FIFO Reset (FUN_CODE_10d9)"
FIFORESET = 0x80; // NAKALL: NAK all host transfers during reset FIFORESET = 0x80; // NAKALL: NAK all host transfers during reset
// 3-NOP SYNCDELAY // 3-NOP SYNCDELAY
FIFORESET = 0x02; // Reset EP2 FIFO FIFORESET = 0x02; // Reset EP2 FIFO
// 3-NOP SYNCDELAY // 3-NOP SYNCDELAY
FIFORESET = 0x04; // Reset EP4 FIFO FIFORESET = 0x04; // Reset EP4 FIFO
// 3-NOP SYNCDELAY // 3-NOP SYNCDELAY
FIFORESET = 0x06; // Reset EP6 FIFO FIFORESET = 0x06; // Reset EP6 FIFO
// 3-NOP SYNCDELAY // 3-NOP SYNCDELAY
FIFORESET = 0x08; // Reset EP8 FIFO FIFORESET = 0x08; // Reset EP8 FIFO
// 3-NOP SYNCDELAY // 3-NOP SYNCDELAY
FIFORESET = 0x00; // Release NAKALL FIFORESET = 0x00; // Release NAKALL
``` ```
The triple-NOP delays (mandatory SYNCDELAY) between writes are required by the FX2 architecture: XRAM register writes take 2 cycles to propagate, and back-to-back writes to the same register need at least 3 instruction cycles. The triple-NOP delays (mandatory SYNCDELAY) between writes are required by the FX2 architecture: XRAM register writes take 2 cycles to propagate, and back-to-back writes to the same register need at least 3 instruction cycles.
## ARM_TRANSFER Command (0x85) ## ARM_TRANSFER Command (0x85)
The host issues vendor command 0x85 to start or stop the MPEG-2 transport stream. The handler checks the [configuration status byte](/usb/config-status/) bit 0 (demodulator active) before proceeding. The host issues vendor command 0x85 to start or stop the MPEG-2 transport stream. The handler checks the [configuration status byte](/usb/config-status/) bit 0 (demodulator active) before proceeding.
<Tabs> <Tabs>
<TabItem label="Start Streaming"> <TabItem label="Start Streaming">
When `wValue=1` and the demodulator is active: When `wValue=1` and the demodulator is active:
<Steps> <Steps>
1. **Set streaming flag** -- config_byte bit 7 = 1 (bmArmed). 1. **Set streaming flag** -- config_byte bit 7 = 1 (bmArmed).
2. **Load GPIF transaction count** -- GPIFTCB3:2 = 0x8000 (2 GB, effectively infinite). 2. **Load GPIF transaction count** -- GPIFTCB3:2 = 0x8000 (2 GB, effectively infinite).
3. **Reset address and byte count** -- Clear GPIF address registers and EP2 FIFO byte count. 3. **Reset address and byte count** -- Clear GPIF address registers and EP2 FIFO byte count.
4. **Assert TS_EN** -- P3.5 LOW (BCM4500 transport stream output enabled). 4. **Assert TS_EN** -- P3.5 LOW (BCM4500 transport stream output enabled).
5. **Wait for initial GPIF transaction** -- Poll GPIFTRIG bit 7 (DONE) until set. 5. **Wait for initial GPIF transaction** -- Poll GPIFTRIG bit 7 (DONE) until set.
6. **De-assert TS_EN** -- P3.5 HIGH. 6. **De-assert TS_EN** -- P3.5 HIGH.
7. **Trigger continuous GPIF read** -- GPIFTRIG = 0x04 (read direction, EP2 select). 7. **Trigger continuous GPIF read** -- GPIFTRIG = 0x04 (read direction, EP2 select).
8. **Set streaming indicator** -- P0.7 LOW. 8. **Set streaming indicator** -- P0.7 LOW.
</Steps> </Steps>
```asm title="Start Streaming (Rev.2 at CODE:0D84)" ```asm title="Start Streaming (Rev.2 at CODE:0D84)"
ORL 0x4e, #0x80 ; config_byte |= 0x80 (streaming flag) ORL 0x4e, #0x80 ; config_byte |= 0x80 (streaming flag)
MOV DPTR, #0xE630 ; GPIFTCB3 MOV DPTR, #0xE630 ; GPIFTCB3
MOV A, #0x80 MOV A, #0x80
MOVX @DPTR, A ; GPIFTCB3 = 0x80 (huge transaction count) MOVX @DPTR, A ; GPIFTCB3 = 0x80 (huge transaction count)
; ... address/FIFO reset ... ; ... address/FIFO reset ...
ANL 0xb0, #0xDF ; P3 &= 0xDF -> P3.5 = 0 (TS_EN assert) ANL 0xb0, #0xDF ; P3 &= 0xDF -> P3.5 = 0 (TS_EN assert)
; Poll GPIFTRIG.DONE ... ; Poll GPIFTRIG.DONE ...
ORL 0xb0, #0x20 ; P3 |= 0x20 -> P3.5 = 1 ORL 0xb0, #0x20 ; P3 |= 0x20 -> P3.5 = 1
MOV 0xbb, #0x04 ; GPIFTRIG = 0x04 (read EP2) MOV 0xbb, #0x04 ; GPIFTRIG = 0x04 (read EP2)
ANL 0x80, #0x7F ; P0 &= 0x7F -> P0.7 = 0 (streaming) ANL 0x80, #0x7F ; P0 &= 0x7F -> P0.7 = 0 (streaming)
``` ```
</TabItem> </TabItem>
<TabItem label="Stop Streaming"> <TabItem label="Stop Streaming">
When `wValue=0` and currently streaming (config_byte bit 7 set): When `wValue=0` and currently streaming (config_byte bit 7 set):
<Steps> <Steps>
1. **Set stopped indicator** -- P0.7 HIGH. 1. **Set stopped indicator** -- P0.7 HIGH.
2. **Force-flush buffer** -- EP2FIFOBCH = 0xFF (skip current FIFO packet). 2. **Force-flush buffer** -- EP2FIFOBCH = 0xFF (skip current FIFO packet).
3. **Wait for GPIF idle** -- Poll GPIFTRIG bit 7 (DONE) until set. 3. **Wait for GPIF idle** -- Poll GPIFTRIG bit 7 (DONE) until set.
4. **Discard partial packet** -- OUTPKTEND = 0x82 (skip bit set, EP2 select). 4. **Discard partial packet** -- OUTPKTEND = 0x82 (skip bit set, EP2 select).
5. **Clear streaming flag** -- config_byte bit 7 = 0. 5. **Clear streaming flag** -- config_byte bit 7 = 0.
6. **De-assert control lines** -- P3 bits 7:5 = 1 (all BCM4500 controls idle). 6. **De-assert control lines** -- P3 bits 7:5 = 1 (all BCM4500 controls idle).
</Steps> </Steps>
```asm title="Stop Streaming (Rev.2 at CODE:0DE1)" ```asm title="Stop Streaming (Rev.2 at CODE:0DE1)"
ORL 0x80, #0x80 ; P0 |= 0x80 -> P0.7 = 1 (stopped) ORL 0x80, #0x80 ; P0 |= 0x80 -> P0.7 = 1 (stopped)
MOV DPTR, #0xE6F5 ; EP2FIFOBCH MOV DPTR, #0xE6F5 ; EP2FIFOBCH
MOV A, #0xFF MOV A, #0xFF
MOVX @DPTR, A ; Force flush MOVX @DPTR, A ; Force flush
; Poll GPIFTRIG.DONE ... ; Poll GPIFTRIG.DONE ...
MOV DPTR, #0xE648 ; OUTPKTEND MOV DPTR, #0xE648 ; OUTPKTEND
MOV A, #0x82 ; Skip=1, EP2 MOV A, #0x82 ; Skip=1, EP2
MOVX @DPTR, A ; Discard partial packet MOVX @DPTR, A ; Discard partial packet
ANL 0x4e, #0x7F ; config_byte &= 0x7F (clear streaming) ANL 0x4e, #0x7F ; config_byte &= 0x7F (clear streaming)
ORL 0xb0, #0xE0 ; P3 |= 0xE0 (de-assert all controls) ORL 0xb0, #0xE0 ; P3 |= 0xE0 (de-assert all controls)
``` ```
</TabItem> </TabItem>
</Tabs> </Tabs>
## Interrupt Handling ## Interrupt Handling
INT4 and INT6 (GPIF/FIFO events) share a common handler that sets a software flag and clears EXIF.4: INT4 and INT6 (GPIF/FIFO events) share a common handler that sets a software flag and clears EXIF.4:
```asm title="GPIF Interrupt Handler (Rev.2 at CODE:2084)" ```asm title="GPIF Interrupt Handler (Rev.2 at CODE:2084)"
PUSH A PUSH A
PUSH DPH PUSH DPH
PUSH DPL PUSH DPL
SETB 0x01 ; Set GPIF event flag (_0_1) SETB 0x01 ; Set GPIF event flag (_0_1)
ANL 0x91, #0xEF ; Clear EXIF.4 (INT4/INT6 IRQ flag) ANL 0x91, #0xEF ; Clear EXIF.4 (INT4/INT6 IRQ flag)
MOV DPTR, #0xE65D ; GPIFIRQ MOV DPTR, #0xE65D ; GPIFIRQ
MOV A, #0x01 MOV A, #0x01
MOVX @DPTR, A ; Clear GPIFIRQ bit 0 MOVX @DPTR, A ; Clear GPIFIRQ bit 0
POP DPL POP DPL
POP DPH POP DPH
POP A POP A
RETI RETI
``` ```
The main loop polls this flag, enters CPU idle mode (PCON.0) between events, and checks EP2CS for buffer availability before re-arming the GPIF. The FLOWSTATE engine (FSEN=1) automatically re-triggers GPIF transactions when EP2 buffers become available. The main loop polls this flag, enters CPU idle mode (PCON.0) between events, and checks EP2CS for buffer availability before re-arming the GPIF. The FLOWSTATE engine (FSEN=1) automatically re-triggers GPIF transactions when EP2 buffers become available.
## GPIF Interrupt Enable (GPIFIE) ## GPIF Interrupt Enable (GPIFIE)
| Bit | Name | Enabled | Purpose | | Bit | Name | Enabled | Purpose |
|-----|------|---------|---------| |-----|------|---------|---------|
| 0 | GPIFWF | Yes | Waveform completion interrupt | | 0 | GPIFWF | Yes | Waveform completion interrupt |
| 1 | (reserved) | No | -- | | 1 | (reserved) | No | -- |
| 2 | GPIFTCEXP | Yes | Transaction count expired | | 2 | GPIFTCEXP | Yes | Transaction count expired |
| 3 | GPIFGPIFDONE | Yes | GPIF operation done | | 3 | GPIFGPIFDONE | Yes | GPIF operation done |
| 4 | GPIFFF | Yes | FIFO flag interrupt | | 4 | GPIFFF | Yes | FIFO flag interrupt |
| 5 | GPIFWF2 | Yes | Waveform 2 completion | | 5 | GPIFWF2 | Yes | Waveform 2 completion |
## Throughput Analysis ## Throughput Analysis
| Metric | Value | | Metric | Value |
|--------|-------| |--------|-------|
| USB 2.0 HS bulk (theoretical) | 480 Mbps | | USB 2.0 HS bulk (theoretical) | 480 Mbps |
| USB 2.0 HS bulk (practical) | ~280 Mbps (~35 MB/s) | | USB 2.0 HS bulk (practical) | ~280 Mbps (~35 MB/s) |
| GPIF engine (theoretical) | 48 MHz x 8 bits = 384 Mbps | | GPIF engine (theoretical) | 48 MHz x 8 bits = 384 Mbps |
| Typical DVB-S TS rate | 1--5 MB/s | | Typical DVB-S TS rate | 1--5 MB/s |
| Maximum DVB-S2 rate (hypothetical) | ~7.25 MB/s (58 Mbps) | | Maximum DVB-S2 rate (hypothetical) | ~7.25 MB/s (58 Mbps) |
The USB/GPIF path has approximately 5x headroom even at the maximum theoretical data rate. The bottleneck for all supported modes is the satellite link, not the USB data path. The USB/GPIF path has approximately 5x headroom even at the maximum theoretical data rate. The bottleneck for all supported modes is the satellite link, not the USB data path.
## Timing ## Timing
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| GPIF clock | 48 MHz internal | | GPIF clock | 48 MHz internal |
| CPU clock | 48 MHz | | CPU clock | 48 MHz |
| GPIF mode | Asynchronous (RDY pin handshaking) | | GPIF mode | Asynchronous (RDY pin handshaking) |
| NOP delays | 3 NOPs between XRAM writes (~62.5 ns at 48 MHz) | | NOP delays | 3 NOPs between XRAM writes (~62.5 ns at 48 MHz) |
| EP2 buffer commit | Automatic via AUTOIN on FIFO fullness | | EP2 buffer commit | Automatic via AUTOIN on FIFO fullness |
| GPIF re-trigger | Automatic via FLOWSTATE when EP2 buffer space available | | GPIF re-trigger | Automatic via FLOWSTATE when EP2 buffer space available |
## Cross-Version Comparison ## Cross-Version Comparison
The GPIF streaming path is functionally identical across all three firmware versions. Only code addresses differ due to recompilation: The GPIF streaming path is functionally identical across all three firmware versions. Only code addresses differ due to recompilation:
| Aspect | v2.06 | v2.13 FW1 | Rev.2 v2.10 | | Aspect | v2.06 | v2.13 FW1 | Rev.2 v2.10 |
|--------|-------|-----------|-------------| |--------|-------|-----------|-------------|
| ARM_TRANSFER handler | CODE:0110 | CODE:0110 | CODE:00FA | | ARM_TRANSFER handler | CODE:0110 | CODE:0110 | CODE:00FA |
| GPIF control function | CODE:1919 | CODE:1800 | CODE:0D7C | | GPIF control function | CODE:1919 | CODE:1800 | CODE:0D7C |
| Config byte IRAM | 0x6D | 0x4F | 0x4E | | Config byte IRAM | 0x6D | 0x4F | 0x4E |
| EP2FIFOCFG value | 0x0C | 0x0C | 0x0C | | EP2FIFOCFG value | 0x0C | 0x0C | 0x0C |
| IFCONFIG value | 0xEE | 0xEE | 0xEE | | IFCONFIG value | 0xEE | 0xEE | 0xEE |
| FLOWSTATEA setting | OR 0x09 | OR 0x09 | OR 0x09 | | FLOWSTATEA setting | OR 0x09 | OR 0x09 | OR 0x09 |

View File

@ -1,241 +1,241 @@
--- ---
title: BCM4500 Register Map title: BCM4500 Register Map
description: Definitive register lookup for BCM4500 direct registers, indirect registers, FX2 XRAM/IRAM locations, and I2C controller addresses. description: Definitive register lookup for BCM4500 direct registers, indirect registers, FX2 XRAM/IRAM locations, and I2C controller addresses.
--- ---
import { Badge, Aside } from '@astrojs/starlight/components'; import { Badge, Aside } from '@astrojs/starlight/components';
<Aside type="caution" title="Reverse-Engineered Data"> <Aside type="caution" title="Reverse-Engineered Data">
No public BCM4500 datasheet exists. All register addresses and functions on this page were determined through firmware disassembly, I2C bus captures, and behavioral testing. Register names are conventions used throughout this documentation, not official Broadcom nomenclature. No public BCM4500 datasheet exists. All register addresses and functions on this page were determined through firmware disassembly, I2C bus captures, and behavioral testing. Register names are conventions used throughout this documentation, not official Broadcom nomenclature.
</Aside> </Aside>
This page consolidates every known register address used by the SkyWalker-1 hardware into a single lookup reference. This page consolidates every known register address used by the SkyWalker-1 hardware into a single lookup reference.
## BCM4500 Direct Registers ## BCM4500 Direct Registers
These registers are accessed via standard I2C read/write to the BCM4500 at 7-bit address **0x08** (write byte 0x10, read byte 0x11). These registers are accessed via standard I2C read/write to the BCM4500 at 7-bit address **0x08** (write byte 0x10, read byte 0x11).
| Address | Name | R/W | Function | | Address | Name | R/W | Function |
|---------|------|-----|----------| |---------|------|-----|----------|
| 0xA2 | Status | R | Readiness status. Returns 0x02 when powered on, no signal locked. Polled during boot probe and [signal strength readback](/bcm4500/signal-monitoring/). | | 0xA2 | Status | R | Readiness status. Returns 0x02 when powered on, no signal locked. Polled during boot probe and [signal strength readback](/bcm4500/signal-monitoring/). |
| 0xA4 | Lock | R | Signal lock indicator. Bit 5 (mask 0x20) = signal locked. Read by `GET_SIGNAL_LOCK` (0x90). The kernel treats any non-zero value as locked. | | 0xA4 | Lock | R | Signal lock indicator. Bit 5 (mask 0x20) = signal locked. Read by `GET_SIGNAL_LOCK` (0x90). The kernel treats any non-zero value as locked. |
| 0xA6 | Indirect Page | W | Page/address select for the [indirect register protocol](/bcm4500/demodulator/#indirect-register-protocol). Typically written with 0x00 (page 0). | | 0xA6 | Indirect Page | W | Page/address select for the [indirect register protocol](/bcm4500/demodulator/#indirect-register-protocol). Typically written with 0x00 (page 0). |
| 0xA7 | Indirect Data | R/W | Data register for indirect reads and writes. Supports auto-increment for multi-byte writes within a single I2C transaction. | | 0xA7 | Indirect Data | R/W | Data register for indirect reads and writes. Supports auto-increment for multi-byte writes within a single I2C transaction. |
| 0xA8 | Indirect Command | R/W | Command register. Write 0x01 = indirect read, 0x03 = indirect write. Read to poll: bit 0 clear = command complete. | | 0xA8 | Indirect Command | R/W | Command register. Write 0x01 = indirect read, 0x03 = indirect write. Read to poll: bit 0 clear = command complete. |
| 0xF9 | Demod Status | R | Extended demodulator status. Read by `GET_DEMOD_STATUS` (0x99) in v2.13 firmware. Also polled by the v2.13 INT0 handler. Not accessed by v2.06 or Rev.2. | | 0xF9 | Demod Status | R | Extended demodulator status. Read by `GET_DEMOD_STATUS` (0x99) in v2.13 firmware. Also polled by the v2.13 INT0 handler. Not accessed by v2.06 or Rev.2. |
### Indirect Register Triad ### Indirect Register Triad
Registers 0xA6, 0xA7, and 0xA8 form a triad that provides access to the BCM4500's internal register space. The sequence is always: select page (0xA6) &rarr; write/read data (0xA7) &rarr; execute command (0xA8) &rarr; poll 0xA8 for completion. Registers 0xA6, 0xA7, and 0xA8 form a triad that provides access to the BCM4500's internal register space. The sequence is always: select page (0xA6) &rarr; write/read data (0xA7) &rarr; execute command (0xA8) &rarr; poll 0xA8 for completion.
See [Demodulator &mdash; Indirect Register Protocol](/bcm4500/demodulator/#indirect-register-protocol) for the full byte-level I2C sequences. See [Demodulator &mdash; Indirect Register Protocol](/bcm4500/demodulator/#indirect-register-protocol) for the full byte-level I2C sequences.
## Indirect Registers (Page 0) ## Indirect Registers (Page 0)
These are the BCM4500 internal registers accessed through the 0xA6/0xA7/0xA8 indirect protocol. All known registers are on page 0x00. These are the BCM4500 internal registers accessed through the 0xA6/0xA7/0xA8 indirect protocol. All known registers are on page 0x00.
### Signal Quality ### Signal Quality
| Register | Size | Function | Read By | | Register | Size | Function | Read By |
|----------|------|----------|---------| |----------|------|----------|---------|
| 0x00--0x01 | 2 bytes | SNR value (16-bit, little-endian). Bytes 0--1 of `GET_SIGNAL_STRENGTH` (0x87) response. | [Signal Monitoring](/bcm4500/signal-monitoring/) | | 0x00--0x01 | 2 bytes | SNR value (16-bit, little-endian). Bytes 0--1 of `GET_SIGNAL_STRENGTH` (0x87) response. | [Signal Monitoring](/bcm4500/signal-monitoring/) |
| 0x02--0x05 | 4 bytes | AGC and diagnostic data. Bytes 2--5 of `GET_SIGNAL_STRENGTH` (0x87) response. | [Signal Monitoring](/bcm4500/signal-monitoring/) | | 0x02--0x05 | 4 bytes | AGC and diagnostic data. Bytes 2--5 of `GET_SIGNAL_STRENGTH` (0x87) response. | [Signal Monitoring](/bcm4500/signal-monitoring/) |
### Initialization Blocks ### Initialization Blocks
Three blocks written during BCM4500 firmware load. The first byte of each block is the starting register address. Three blocks written during BCM4500 firmware load. The first byte of each block is the starting register address.
| Block | Start Reg | Length | Data (hex) | Purpose | | Block | Start Reg | Length | Data (hex) | Purpose |
|-------|-----------|--------|------------|---------| |-------|-----------|--------|------------|---------|
| 0 | 0x06 | 7 bytes | `06 0b 17 38 9f d9 80` | Primary demod configuration | | 0 | 0x06 | 7 bytes | `06 0b 17 38 9f d9 80` | Primary demod configuration |
| 1 | 0x07 | 8 bytes | `07 09 39 4f 00 65 b7 10` | Secondary demod configuration | | 1 | 0x07 | 8 bytes | `07 09 39 4f 00 65 b7 10` | Secondary demod configuration |
| 2 | 0x0F | 3 bytes | `0f 0c 09` | Final demod configuration | | 2 | 0x0F | 3 bytes | `0f 0c 09` | Final demod configuration |
<Aside type="note" title="Init Block Overlap"> <Aside type="note" title="Init Block Overlap">
Blocks 0 and 1 both write to register 0x07 and above, meaning block 1 overwrites the tail end of block 0. This is intentional: block 0 sets initial defaults, block 1 refines registers 0x07--0x0E, and block 2 configures the 0x0F--0x11 range independently. All stock firmware versions use the same init block data. Blocks 0 and 1 both write to register 0x07 and above, meaning block 1 overwrites the tail end of block 0. This is intentional: block 0 sets initial defaults, block 1 refines registers 0x07--0x0E, and block 2 configures the 0x0F--0x11 range independently. All stock firmware versions use the same init block data.
</Aside> </Aside>
### Tuning Configuration ### Tuning Configuration
After modulation dispatch, the [tuning protocol](/bcm4500/tuning-protocol/) writes frequency, symbol rate, FEC, and modulation parameters into BCM4500 page 0 registers via the indirect write protocol. The exact target register range depends on the configuration data length (typically 12--18 bytes starting at register 0x00). After modulation dispatch, the [tuning protocol](/bcm4500/tuning-protocol/) writes frequency, symbol rate, FEC, and modulation parameters into BCM4500 page 0 registers via the indirect write protocol. The exact target register range depends on the configuration data length (typically 12--18 bytes starting at register 0x00).
## FX2 XRAM Locations ## FX2 XRAM Locations
External RAM (XRAM) addresses used by the FX2 microcontroller for tuning state and configuration. These are **not** BCM4500 registers &mdash; they are FX2 memory locations that hold data destined for or read from the demodulator. External RAM (XRAM) addresses used by the FX2 microcontroller for tuning state and configuration. These are **not** BCM4500 registers &mdash; they are FX2 memory locations that hold data destined for or read from the demodulator.
### Modulation Configuration ### Modulation Configuration
| Address | Name | Function | | Address | Name | Function |
|---------|------|----------| |---------|------|----------|
| 0xE0EB | FEC Code Rate | Looked up from the FEC table for the active modulation. DCII modes use fixed value 0xFC. DSS/BPSK modes OR the lookup with 0x80. | | 0xE0EB | FEC Code Rate | Looked up from the FEC table for the active modulation. DCII modes use fixed value 0xFC. DSS/BPSK modes OR the lookup with 0x80. |
| 0xE0EC | Modulation Type | 0x09 for DVB-S, Turbo, DSS, and BPSK modes. DCII modes load from the DCII lookup table. | | 0xE0EC | Modulation Type | 0x09 for DVB-S, Turbo, DSS, and BPSK modes. DCII modes load from the DCII lookup table. |
| 0xE0F5 | Demod Mode | 0x10 for most modes. DCII variants use 0x10 (combo), 0x11 (offset QPSK), 0x12 (I-stream), or 0x16 (Q-stream). | | 0xE0F5 | Demod Mode | 0x10 for most modes. DCII variants use 0x10 (combo), 0x11 (offset QPSK), 0x12 (I-stream), or 0x16 (Q-stream). |
| 0xE0F6 | Turbo Flag | 0x00 = standard FEC. 0x01 = turbo FEC (QPSK/8PSK/16QAM turbo modes). | | 0xE0F6 | Turbo Flag | 0x00 = standard FEC. 0x01 = turbo FEC (QPSK/8PSK/16QAM turbo modes). |
### Tuning Parameters ### Tuning Parameters
| Address | Size | Content | Source | | Address | Size | Content | Source |
|---------|------|---------|--------| |---------|------|---------|--------|
| 0xE0CB--0xE0CE | 4 bytes | Symbol rate (big-endian) | Byte-reversed from EP0BUF[0--3] during `TUNE_8PSK` | | 0xE0CB--0xE0CE | 4 bytes | Symbol rate (big-endian) | Byte-reversed from EP0BUF[0--3] during `TUNE_8PSK` |
| 0xE0DB--0xE0DE | 4 bytes | IF frequency (big-endian) | Byte-reversed from EP0BUF[4--7] during `TUNE_8PSK` | | 0xE0DB--0xE0DE | 4 bytes | IF frequency (big-endian) | Byte-reversed from EP0BUF[4--7] during `TUNE_8PSK` |
### FEC Rate Lookup Tables ### FEC Rate Lookup Tables
Populated at boot from CODE-space initialization tables. Indexed by the FEC rate byte from the `TUNE_8PSK` command payload. Populated at boot from CODE-space initialization tables. Indexed by the FEC rate byte from the `TUNE_8PSK` command payload.
| Base Address | Modulation | Max Index | Rates | | Base Address | Modulation | Max Index | Rates |
|-------------|-----------|-----------|-------| |-------------|-----------|-----------|-------|
| 0xE0B1 | Turbo 8PSK | 5 | Turbo-specific code rates | | 0xE0B1 | Turbo 8PSK | 5 | Turbo-specific code rates |
| 0xE0B7 | Turbo QPSK | 5 | Turbo-specific code rates | | 0xE0B7 | Turbo QPSK | 5 | Turbo-specific code rates |
| 0xE0BC | Turbo 16QAM | 1 | Single code rate | | 0xE0BC | Turbo 16QAM | 1 | Single code rate |
| 0xE0BD | DCII (all variants) | 9 | Combined code + modulation values | | 0xE0BD | DCII (all variants) | 9 | Combined code + modulation values |
| 0xE0F9 | DVB-S QPSK / DSS / BPSK | 7 | 1/2, 2/3, 3/4, 5/6, 7/8, auto, none | | 0xE0F9 | DVB-S QPSK / DSS / BPSK | 7 | 1/2, 2/3, 3/4, 5/6, 7/8, auto, none |
### FW2/FW3 External Configuration ### FW2/FW3 External Configuration
| Address | Size | Content | | Address | Size | Content |
|---------|------|---------| |---------|------|---------|
| 0xE080--0xE08E | 15 bytes | External calibration data loaded by [FW2 and FW3](/firmware/fw213-variants/) into demod registers at 0xE6C0--0xE6CD. Not used by FW1 (hardcoded config). | | 0xE080--0xE08E | 15 bytes | External calibration data loaded by [FW2 and FW3](/firmware/fw213-variants/) into demod registers at 0xE6C0--0xE6CD. Not used by FW1 (hardcoded config). |
### USB Endpoint Buffer ### USB Endpoint Buffer
| Address | Size | Content | | Address | Size | Content |
|---------|------|---------| |---------|------|---------|
| 0xE740--0xE749 | 10 bytes | EP0BUF &mdash; USB control transfer buffer. Contains the raw `TUNE_8PSK` payload before parsing. | | 0xE740--0xE749 | 10 bytes | EP0BUF &mdash; USB control transfer buffer. Contains the raw `TUNE_8PSK` payload before parsing. |
## FX2 IRAM by Firmware Version ## FX2 IRAM by Firmware Version
Internal RAM (IRAM) addresses vary between firmware versions due to different stack pointer placement. This table maps the key locations for each version. Internal RAM (IRAM) addresses vary between firmware versions due to different stack pointer placement. This table maps the key locations for each version.
### Stack and Status ### Stack and Status
| Location | v2.06 | Rev.2 v2.10 | v2.13 FW1/FW2 | v2.13 FW3 | | Location | v2.06 | Rev.2 v2.10 | v2.13 FW1/FW2 | v2.13 FW3 |
|----------|-------|-------------|---------------|-----------| |----------|-------|-------------|---------------|-----------|
| Stack pointer (SP) | 0x72 | 0x4F | 0x50 | 0x52 | | Stack pointer (SP) | 0x72 | 0x4F | 0x50 | 0x52 |
| Config status byte | 0x6D | 0x4E | 0x4F | 0x51 | | Config status byte | 0x6D | 0x4E | 0x4F | 0x51 |
| I2C buffer high | -- | 0x48 | 0x48 | 0x4A | | I2C buffer high | -- | 0x48 | 0x48 | 0x4A |
| I2C buffer low | -- | 0x49 | 0x49 | 0x4B | | I2C buffer low | -- | 0x49 | 0x49 | 0x4B |
The config status byte is returned by `GET_8PSK_CONFIG` (0x80). See [Config Status](/usb/config-status/) for bit definitions. The config status byte is returned by `GET_8PSK_CONFIG` (0x80). See [Config Status](/usb/config-status/) for bit definitions.
### Tuning Parameter Storage ### Tuning Parameter Storage
| Location | Address | Function | | Location | Address | Function |
|----------|---------|----------| |----------|---------|----------|
| Modulation type | 0x4D | Copied from EP0BUF[8] during `TUNE_8PSK` parsing | | Modulation type | 0x4D | Copied from EP0BUF[8] during `TUNE_8PSK` parsing |
| FEC rate index | 0x4F | Copied from EP0BUF[9] during `TUNE_8PSK` parsing | | FEC rate index | 0x4F | Copied from EP0BUF[9] during `TUNE_8PSK` parsing |
<Aside type="note"> <Aside type="note">
On v2.13 FW1/FW2, the FEC rate index (IRAM 0x4F) shares the same address as the config status byte. The firmware distinguishes between contexts &mdash; the FEC index is only written during tune operations, while config status is read/written at other times. FW3 avoids this collision by moving the config status to 0x51. On v2.13 FW1/FW2, the FEC rate index (IRAM 0x4F) shares the same address as the config status byte. The firmware distinguishes between contexts &mdash; the FEC index is only written during tune operations, while config status is read/written at other times. FW3 avoids this collision by moving the config status to 0x51.
</Aside> </Aside>
### Custom Firmware (v3.01+) ### Custom Firmware (v3.01+)
The custom firmware built with SDCC + fx2lib uses C variables instead of fixed IRAM addresses. The compiler manages allocation, so addresses are not guaranteed stable across builds. Key variables: The custom firmware built with SDCC + fx2lib uses C variables instead of fixed IRAM addresses. The compiler manages allocation, so addresses are not guaranteed stable across builds. Key variables:
| Variable | Type | Purpose | | Variable | Type | Purpose |
|----------|------|---------| |----------|------|---------|
| `config_status` | `volatile BYTE` | Configuration status byte | | `config_status` | `volatile BYTE` | Configuration status byte |
| `boot_stage` | `volatile BYTE` | Boot progress (0x00 = not started, 0xFF = complete) | | `boot_stage` | `volatile BYTE` | Boot progress (0x00 = not started, 0xFF = complete) |
| `i2c_buf[16]` | `__xdata BYTE` | I2C scratch buffer for writes | | `i2c_buf[16]` | `__xdata BYTE` | I2C scratch buffer for writes |
| `i2c_rd[8]` | `__xdata BYTE` | I2C scratch buffer for reads | | `i2c_rd[8]` | `__xdata BYTE` | I2C scratch buffer for reads |
| `tm_result[10]` | `__xdata BYTE` | Tune monitor result buffer | | `tm_result[10]` | `__xdata BYTE` | Tune monitor result buffer |
## FX2 USB Controller Registers ## FX2 USB Controller Registers
Core FX2LP registers used for USB control transfers, CPU management, and peripheral configuration. Core FX2LP registers used for USB control transfers, CPU management, and peripheral configuration.
### CPU and Peripheral Config ### CPU and Peripheral Config
| Register | Address | Function | | Register | Address | Function |
|----------|---------|----------| |----------|---------|----------|
| CPUCS | 0xE600 | CPU control/status. Write 0x01 to halt, 0x00 to run. Bits 4:3 select clock speed (10 = 48 MHz). | | CPUCS | 0xE600 | CPU control/status. Write 0x01 to halt, 0x00 to run. Bits 4:3 select clock speed (10 = 48 MHz). |
| IFCONFIG | 0xE601 | Interface configuration. Value 0xEE = internal 48 MHz clock, GPIF master, async mode. | | IFCONFIG | 0xE601 | Interface configuration. Value 0xEE = internal 48 MHz clock, GPIF master, async mode. |
| REVCTL | 0xE60B | Revision control. Value 0x03 = NOAUTOARM + SKIPCOMMIT (required for manual EP management). | | REVCTL | 0xE60B | Revision control. Value 0x03 = NOAUTOARM + SKIPCOMMIT (required for manual EP management). |
| EP2FIFOCFG | 0xE618 | EP2 FIFO configuration. Value 0x0C = AUTOIN + ZEROLENIN, 8-bit data bus. | | EP2FIFOCFG | 0xE618 | EP2 FIFO configuration. Value 0x0C = AUTOIN + ZEROLENIN, 8-bit data bus. |
### USB Setup Data (SETUPDAT) ### USB Setup Data (SETUPDAT)
Populated by the FX2 hardware when a SETUP packet arrives on EP0. The vendor command dispatcher reads `SETUPDAT[1]` to determine the command. Populated by the FX2 hardware when a SETUP packet arrives on EP0. The vendor command dispatcher reads `SETUPDAT[1]` to determine the command.
| Register | Address | Content | | Register | Address | Content |
|----------|---------|---------| |----------|---------|---------|
| SETUPDAT[0] | 0xE6B8 | bmRequestType (0x40 = vendor OUT, 0xC0 = vendor IN) | | SETUPDAT[0] | 0xE6B8 | bmRequestType (0x40 = vendor OUT, 0xC0 = vendor IN) |
| SETUPDAT[1] | 0xE6B9 | bRequest (vendor command ID: 0x80--0xB9) | | SETUPDAT[1] | 0xE6B9 | bRequest (vendor command ID: 0x80--0xB9) |
| SETUPDAT[2] | 0xE6BA | wValueL | | SETUPDAT[2] | 0xE6BA | wValueL |
| SETUPDAT[3] | 0xE6BB | wValueH | | SETUPDAT[3] | 0xE6BB | wValueH |
| SETUPDAT[4] | 0xE6BC | wIndexL | | SETUPDAT[4] | 0xE6BC | wIndexL |
| SETUPDAT[5] | 0xE6BD | wIndexH | | SETUPDAT[5] | 0xE6BD | wIndexH |
| SETUPDAT[6] | 0xE6BE | wLengthL | | SETUPDAT[6] | 0xE6BE | wLengthL |
| SETUPDAT[7] | 0xE6BF | wLengthH | | SETUPDAT[7] | 0xE6BF | wLengthH |
### EP0 Buffer ### EP0 Buffer
| Register | Address | Function | | Register | Address | Function |
|----------|---------|----------| |----------|---------|----------|
| EP0BCH | 0xE68A | EP0 byte count high. | | EP0BCH | 0xE68A | EP0 byte count high. |
| EP0BCL | 0xE68B | EP0 byte count low. Writing this register arms the EP0 IN transfer. | | EP0BCL | 0xE68B | EP0 byte count low. Writing this register arms the EP0 IN transfer. |
| EP0BUF | 0xE740 | EP0 data buffer start (64 bytes). Contains [TUNE_8PSK](/bcm4500/tuning-protocol/) payload bytes 0xE740--0xE749. | | EP0BUF | 0xE740 | EP0 data buffer start (64 bytes). Contains [TUNE_8PSK](/bcm4500/tuning-protocol/) payload bytes 0xE740--0xE749. |
### LNB Control (XRAM) ### LNB Control (XRAM)
| Address | Function | | Address | Function |
|---------|----------| |---------|----------|
| 0xE0B6 | LNB voltage control register. Written by `SET_LNB_VOLTAGE` (0x8B) in the custom firmware. | | 0xE0B6 | LNB voltage control register. Written by `SET_LNB_VOLTAGE` (0x8B) in the custom firmware. |
## FX2 I2C Controller ## FX2 I2C Controller
The Cypress FX2LP's built-in I2C master controller uses three hardware registers in the SFR-mapped XRAM space. The Cypress FX2LP's built-in I2C master controller uses three hardware registers in the SFR-mapped XRAM space.
| Register | Address | Function | | Register | Address | Function |
|----------|---------|----------| |----------|---------|----------|
| I2CS | 0xE678 | Control/Status. Bit fields: DONE (bit 0), ACK (bit 1), BERR (bit 2), ID (bits 4:3), LASTRD (bit 5), STOP (bit 6), START (bit 7). | | I2CS | 0xE678 | Control/Status. Bit fields: DONE (bit 0), ACK (bit 1), BERR (bit 2), ID (bits 4:3), LASTRD (bit 5), STOP (bit 6), START (bit 7). |
| I2DAT | 0xE679 | Data register. Write to transmit a byte, read to receive. First write after START sends the slave address byte. | | I2DAT | 0xE679 | Data register. Write to transmit a byte, read to receive. First write after START sends the slave address byte. |
| I2CTL | 0xE67A | Control register. Bit 0 = 400 kHz mode (set by all firmware versions at init). Bit 1 = STOPIE (stop interrupt enable). | | I2CTL | 0xE67A | Control register. Bit 0 = 400 kHz mode (set by all firmware versions at init). Bit 1 = STOPIE (stop interrupt enable). |
### I2C Bus Addresses ### I2C Bus Addresses
| 7-bit Address | 8-bit Write | 8-bit Read | Device | | 7-bit Address | 8-bit Write | 8-bit Read | Device |
|--------------|-------------|------------|--------| |--------------|-------------|------------|--------|
| 0x08 | 0x10 | 0x11 | BCM4500 demodulator (operating address) | | 0x08 | 0x10 | 0x11 | BCM4500 demodulator (operating address) |
| 0x10 | 0x20 | 0x21 | Tuner / LNB controller | | 0x10 | 0x20 | 0x21 | Tuner / LNB controller |
| 0x51 | 0xA2 | 0xA3 | Configuration EEPROM (serial number, calibration, firmware storage) | | 0x51 | 0xA2 | 0xA3 | Configuration EEPROM (serial number, calibration, firmware storage) |
| 0x3F | 0x7E | 0x7F | BCM4500 alternate probe address (v2.13 boot detection only) | | 0x3F | 0x7E | 0x7F | BCM4500 alternate probe address (v2.13 boot detection only) |
| 0x7F | 0xFE | 0xFF | BCM4500 alternate probe address (v2.13 boot detection only) | | 0x7F | 0xFE | 0xFF | BCM4500 alternate probe address (v2.13 boot detection only) |
See [I2C Bus Architecture](/i2c/bus-architecture/) for bus topology and the [STOP Corruption Bug](/i2c/stop-corruption-bug/) for the spurious STOP issue affecting the FX2 controller. See [I2C Bus Architecture](/i2c/bus-architecture/) for bus topology and the [STOP Corruption Bug](/i2c/stop-corruption-bug/) for the spurious STOP issue affecting the FX2 controller.
## Cross-Reference Index ## Cross-Reference Index
Every documentation page that references specific registers or memory addresses: Every documentation page that references specific registers or memory addresses:
### BCM4500 Direct Registers ### BCM4500 Direct Registers
| Register | Pages | | Register | Pages |
|----------|-------| |----------|-------|
| 0xA2 (Status) | [Demodulator](/bcm4500/demodulator/), [Signal Monitoring](/bcm4500/signal-monitoring/), [Version Comparison](/firmware/version-comparison/) | | 0xA2 (Status) | [Demodulator](/bcm4500/demodulator/), [Signal Monitoring](/bcm4500/signal-monitoring/), [Version Comparison](/firmware/version-comparison/) |
| 0xA4 (Lock) | [Demodulator](/bcm4500/demodulator/), [Signal Monitoring](/bcm4500/signal-monitoring/), [Tuning Protocol](/bcm4500/tuning-protocol/) | | 0xA4 (Lock) | [Demodulator](/bcm4500/demodulator/), [Signal Monitoring](/bcm4500/signal-monitoring/), [Tuning Protocol](/bcm4500/tuning-protocol/) |
| 0xA6/0xA7/0xA8 (Indirect) | [Demodulator](/bcm4500/demodulator/), [Tuning Protocol](/bcm4500/tuning-protocol/), [Signal Monitoring](/bcm4500/signal-monitoring/) | | 0xA6/0xA7/0xA8 (Indirect) | [Demodulator](/bcm4500/demodulator/), [Tuning Protocol](/bcm4500/tuning-protocol/), [Signal Monitoring](/bcm4500/signal-monitoring/) |
| 0xF9 (Demod Status) | [Demodulator](/bcm4500/demodulator/), [Signal Monitoring](/bcm4500/signal-monitoring/), [Version Comparison](/firmware/version-comparison/) | | 0xF9 (Demod Status) | [Demodulator](/bcm4500/demodulator/), [Signal Monitoring](/bcm4500/signal-monitoring/), [Version Comparison](/firmware/version-comparison/) |
### FX2 XRAM ### FX2 XRAM
| Address Range | Pages | | Address Range | Pages |
|--------------|-------| |--------------|-------|
| 0xE0B1--0xE0F9 (FEC tables) | [Tuning Protocol](/bcm4500/tuning-protocol/) | | 0xE0B1--0xE0F9 (FEC tables) | [Tuning Protocol](/bcm4500/tuning-protocol/) |
| 0xE0CB--0xE0DE (Tune params) | [Tuning Protocol](/bcm4500/tuning-protocol/) | | 0xE0CB--0xE0DE (Tune params) | [Tuning Protocol](/bcm4500/tuning-protocol/) |
| 0xE0EB--0xE0F6 (Mod config) | [Tuning Protocol](/bcm4500/tuning-protocol/) | | 0xE0EB--0xE0F6 (Mod config) | [Tuning Protocol](/bcm4500/tuning-protocol/) |
| 0xE080--0xE08E (FW2/FW3 cal) | [FW2.13 Variants](/firmware/fw213-variants/) | | 0xE080--0xE08E (FW2/FW3 cal) | [FW2.13 Variants](/firmware/fw213-variants/) |
### FX2 IRAM ### FX2 IRAM
| Address | Pages | | Address | Pages |
|---------|-------| |---------|-------|
| Config status (version-dependent) | [Config Status](/usb/config-status/), [Version Comparison](/firmware/version-comparison/), [FW2.13 Variants](/firmware/fw213-variants/) | | Config status (version-dependent) | [Config Status](/usb/config-status/), [Version Comparison](/firmware/version-comparison/), [FW2.13 Variants](/firmware/fw213-variants/) |
| SP, I2C buffers | [FW2.13 Variants](/firmware/fw213-variants/), [Version Comparison](/firmware/version-comparison/) | | SP, I2C buffers | [FW2.13 Variants](/firmware/fw213-variants/), [Version Comparison](/firmware/version-comparison/) |
### I2C Controller ### I2C Controller
| Register | Pages | | Register | Pages |
|----------|-------| |----------|-------|
| I2CS/I2DAT/I2CTL (0xE678--0xE67A) | [I2C Bus Architecture](/i2c/bus-architecture/), [STOP Corruption Bug](/i2c/stop-corruption-bug/), [Demodulator](/bcm4500/demodulator/) | | I2CS/I2DAT/I2CTL (0xE678--0xE67A) | [I2C Bus Architecture](/i2c/bus-architecture/), [STOP Corruption Bug](/i2c/stop-corruption-bug/), [Demodulator](/bcm4500/demodulator/) |

View File

@ -1,119 +1,119 @@
--- ---
title: Signal Monitoring title: Signal Monitoring
description: SNR, signal strength, and lock status readback from the BCM4500 demodulator. description: SNR, signal strength, and lock status readback from the BCM4500 demodulator.
--- ---
import { Badge, Aside } from '@astrojs/starlight/components'; import { Badge, Aside } from '@astrojs/starlight/components';
Signal monitoring uses two vendor commands: GET_SIGNAL_LOCK (0x90) for lock status and GET_SIGNAL_STRENGTH (0x87) for SNR and diagnostic data. Both read BCM4500 direct registers via I2C. Signal monitoring uses two vendor commands: GET_SIGNAL_LOCK (0x90) for lock status and GET_SIGNAL_STRENGTH (0x87) for SNR and diagnostic data. Both read BCM4500 direct registers via I2C.
See the [Register Map](/bcm4500/register-map/) for a consolidated lookup of all register addresses referenced on this page. See the [Register Map](/bcm4500/register-map/) for a consolidated lookup of all register addresses referenced on this page.
## Signal Lock (GET_SIGNAL_LOCK, 0x90) ## Signal Lock (GET_SIGNAL_LOCK, 0x90)
Returns 1 byte from BCM4500 direct register 0xA4. Returns 1 byte from BCM4500 direct register 0xA4.
| Bit | Mask | Meaning | | Bit | Mask | Meaning |
|-----|------|---------| |-----|------|---------|
| 5 | 0x20 | Signal locked | | 5 | 0x20 | Signal locked |
| Other bits | -- | Additional status (undocumented) | | Other bits | -- | Additional status (undocumented) |
The kernel driver interprets **any non-zero value** as locked and reports the full lock status: The kernel driver interprets **any non-zero value** as locked and reports the full lock status:
```c title="Kernel Lock Status Flags" ```c title="Kernel Lock Status Flags"
FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER FE_HAS_LOCK | FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_SIGNAL | FE_HAS_CARRIER
``` ```
### Lock States ### Lock States
| Value | State | Description | | Value | State | Description |
|-------|-------|-------------| |-------|-------|-------------|
| 0x00 | <Badge text="Unlocked" variant="danger" /> | No signal or signal not acquired | | 0x00 | <Badge text="Unlocked" variant="danger" /> | No signal or signal not acquired |
| 0x20 | <Badge text="Locked" variant="success" /> | Signal locked, FEC decoding active | | 0x20 | <Badge text="Locked" variant="success" /> | Signal locked, FEC decoding active |
| Other non-zero | <Badge text="Locked" variant="success" /> | Signal acquired, partial status bits | | Other non-zero | <Badge text="Locked" variant="success" /> | Signal acquired, partial status bits |
<Aside type="note" title="Lock Polling"> <Aside type="note" title="Lock Polling">
After sending a [TUNE_8PSK](/bcm4500/tuning-protocol/) command, the host should poll GET_SIGNAL_LOCK repeatedly until a non-zero value is returned or a timeout expires. Typical lock acquisition takes 100-500 ms depending on signal quality and modulation type. After sending a [TUNE_8PSK](/bcm4500/tuning-protocol/) command, the host should poll GET_SIGNAL_LOCK repeatedly until a non-zero value is returned or a timeout expires. Typical lock acquisition takes 100-500 ms depending on signal quality and modulation type.
</Aside> </Aside>
## Signal Strength (GET_SIGNAL_STRENGTH, 0x87) ## Signal Strength (GET_SIGNAL_STRENGTH, 0x87)
Returns 6 bytes. The first two bytes contain a 16-bit SNR value; the remaining bytes are diagnostic register data from the BCM4500. Returns 6 bytes. The first two bytes contain a 16-bit SNR value; the remaining bytes are diagnostic register data from the BCM4500.
### Response Format ### Response Format
| Byte | Content | Notes | | Byte | Content | Notes |
|------|---------|-------| |------|---------|-------|
| 0 | SNR low byte (LSB) | 16-bit little-endian | | 0 | SNR low byte (LSB) | 16-bit little-endian |
| 1 | SNR high byte (MSB) | dBu x 256 units | | 1 | SNR high byte (MSB) | dBu x 256 units |
| 2 | Reserved | BCM4500 diagnostic register | | 2 | Reserved | BCM4500 diagnostic register |
| 3 | Reserved | BCM4500 diagnostic register | | 3 | Reserved | BCM4500 diagnostic register |
| 4 | Reserved | BCM4500 diagnostic register | | 4 | Reserved | BCM4500 diagnostic register |
| 5 | Reserved | BCM4500 diagnostic register | | 5 | Reserved | BCM4500 diagnostic register |
### SNR Scaling ### SNR Scaling
The Windows BDA driver provides the scaling formula: The Windows BDA driver provides the scaling formula:
```c title="SNR to Signal Strength Conversion" ```c title="SNR to Signal Strength Conversion"
uint16_t snr_raw = (buf[1] << 8) | buf[0]; uint16_t snr_raw = (buf[1] << 8) | buf[0];
if (snr_raw <= 0x0F00) { if (snr_raw <= 0x0F00) {
signal_strength = snr_raw * 17; // Maps 0--0x0F00 to 0--65535 signal_strength = snr_raw * 17; // Maps 0--0x0F00 to 0--65535
} else { } else {
signal_strength = 0xFFFF; // 100% at SNR >= 0x0F00 signal_strength = 0xFFFF; // 100% at SNR >= 0x0F00
} }
``` ```
| SNR Raw Value | Signal Strength | Quality | | SNR Raw Value | Signal Strength | Quality |
|--------------|----------------|---------| |--------------|----------------|---------|
| 0x0000 | 0 (0%) | No signal | | 0x0000 | 0 (0%) | No signal |
| 0x0400 | ~27% | Poor | | 0x0400 | ~27% | Poor |
| 0x0800 | ~53% | Fair | | 0x0800 | ~53% | Fair |
| 0x0C00 | ~80% | Good | | 0x0C00 | ~80% | Good |
| 0x0F00 | 100% | Maximum | | 0x0F00 | 100% | Maximum |
| > 0x0F00 | 100% (clamped) | Maximum | | > 0x0F00 | 100% (clamped) | Maximum |
### Firmware Implementation Differences ### Firmware Implementation Differences
The signal strength readback involves I2C transactions to the BCM4500's [indirect register protocol](/bcm4500/demodulator/). The implementation varies between firmware versions: The signal strength readback involves I2C transactions to the BCM4500's [indirect register protocol](/bcm4500/demodulator/). The implementation varies between firmware versions:
| Aspect | v2.06 | Rev.2 v2.10 | v2.13 | | Aspect | v2.06 | Rev.2 v2.10 | v2.13 |
|--------|-------|-------------|-------| |--------|-------|-------------|-------|
| Registers polled | 0xA2, 0xA8, 0xA4 | 0xA2, 0xA8, 0xA4 | Consolidated (1 register) | | Registers polled | 0xA2, 0xA8, 0xA4 | 0xA2, 0xA8, 0xA4 | Consolidated (1 register) |
| Max poll iterations | 6 | 6 | Simplified | | Max poll iterations | 6 | 6 | Simplified |
| Read-back verification | No | Yes (explicit) | No | | Read-back verification | No | Yes (explicit) | No |
| Call chain | 3-register loop | 3-register + verify | Single register path | | Call chain | 3-register loop | 3-register + verify | Single register path |
All versions ultimately return the same 6-byte response format to the host. All versions ultimately return the same 6-byte response format to the host.
## BCM4500 Status Registers ## BCM4500 Status Registers
These direct registers are used for signal monitoring: These direct registers are used for signal monitoring:
| Register | Address | Function | Access | | Register | Address | Function | Access |
|----------|---------|----------|--------| |----------|---------|----------|--------|
| Status | 0xA2 | BCM4500 readiness status | Polled during boot and signal checks | | Status | 0xA2 | BCM4500 readiness status | Polled during boot and signal checks |
| Lock | 0xA4 | Lock/ready; bit 5 = locked | Read by GET_SIGNAL_LOCK (0x90) | | Lock | 0xA4 | Lock/ready; bit 5 = locked | Read by GET_SIGNAL_LOCK (0x90) |
| Command | 0xA8 | Indirect command status; bit 0 = busy | Polled during register operations | | Command | 0xA8 | Indirect command status; bit 0 = busy | Polled during register operations |
| Demod Status | 0xF9 | Extended demod status | Read by GET_DEMOD_STATUS (0x99, v2.13 only) | | Demod Status | 0xF9 | Extended demod status | Read by GET_DEMOD_STATUS (0x99, v2.13 only) |
### Register 0xA2 -- Status ### Register 0xA2 -- Status
Read during boot probing and signal strength readback. Returns 0x02 when the BCM4500 is powered on but no signal is locked. Exact bit field definitions are not documented in the public BCM4500 datasheet. Read during boot probing and signal strength readback. Returns 0x02 when the BCM4500 is powered on but no signal is locked. Exact bit field definitions are not documented in the public BCM4500 datasheet.
### Register 0xA4 -- Lock ### Register 0xA4 -- Lock
The primary lock indicator. The kernel driver reads this as a single byte via GET_SIGNAL_LOCK (0x90). Bit 5 (0x20) is the definitive lock status flag. The primary lock indicator. The kernel driver reads this as a single byte via GET_SIGNAL_LOCK (0x90). Bit 5 (0x20) is the definitive lock status flag.
### Register 0xA8 -- Command ### Register 0xA8 -- Command
Used by the [indirect register protocol](/bcm4500/demodulator/) to track command completion. Bit 0 clear indicates the previous indirect read/write command has completed. This register is polled after every indirect register operation. Used by the [indirect register protocol](/bcm4500/demodulator/) to track command completion. Bit 0 clear indicates the previous indirect read/write command has completed. This register is polled after every indirect register operation.
### Register 0xF9 -- Demod Status (v2.13 only) ### Register 0xF9 -- Demod Status (v2.13 only)
Read by the GET_DEMOD_STATUS vendor command (0x99). Also polled by the v2.13 INT0 handler for demodulator availability detection. This register is not accessed by v2.06 or Rev.2 firmware. Read by the GET_DEMOD_STATUS vendor command (0x99). Also polled by the v2.13 INT0 handler for demodulator availability detection. This register is not accessed by v2.06 or Rev.2 firmware.
<Aside type="tip" title="Custom Firmware Commands"> <Aside type="tip" title="Custom Firmware Commands">
The custom firmware v3.01.0 adds RAW_DEMOD_READ (0xB1) and I2C_DIAG (0xB6) commands that can read any BCM4500 indirect register for diagnostic purposes. See [Vendor Commands](/usb/vendor-commands/) for details. The custom firmware v3.01.0 adds RAW_DEMOD_READ (0xB1) and I2C_DIAG (0xB6) commands that can read any BCM4500 indirect register for diagnostic purposes. See [Vendor Commands](/usb/vendor-commands/) for details.
</Aside> </Aside>

View File

@ -1,260 +1,260 @@
--- ---
title: Tuning Protocol title: Tuning Protocol
description: Complete TUNE_8PSK command protocol including parameter encoding, modulation dispatch, and BCM4500 I2C programming. description: Complete TUNE_8PSK command protocol including parameter encoding, modulation dispatch, and BCM4500 I2C programming.
--- ---
import { Tabs, TabItem, Badge, Steps, Aside } from '@astrojs/starlight/components'; import { Tabs, TabItem, Badge, Steps, Aside } from '@astrojs/starlight/components';
The TUNE_8PSK vendor command (0x86) is the primary mechanism for programming the BCM4500 demodulator to receive a satellite signal. The command carries a 10-byte payload encoding frequency, symbol rate, modulation type, and FEC rate. The firmware parses this payload, dispatches to a modulation-specific handler, programs the BCM4500 via I2C, and the host then polls for signal lock. The TUNE_8PSK vendor command (0x86) is the primary mechanism for programming the BCM4500 demodulator to receive a satellite signal. The command carries a 10-byte payload encoding frequency, symbol rate, modulation type, and FEC rate. The firmware parses this payload, dispatches to a modulation-specific handler, programs the BCM4500 via I2C, and the host then polls for signal lock.
See the [Register Map](/bcm4500/register-map/) for a consolidated lookup of all XRAM addresses and BCM4500 registers referenced on this page. See the [Register Map](/bcm4500/register-map/) for a consolidated lookup of all XRAM addresses and BCM4500 registers referenced on this page.
## Command Format ## Command Format
``` ```
USB SETUP: USB SETUP:
bmRequestType = 0x40 (Vendor, Host-to-Device, OUT) bmRequestType = 0x40 (Vendor, Host-to-Device, OUT)
bRequest = 0x86 (TUNE_8PSK) bRequest = 0x86 (TUNE_8PSK)
wValue = 0x0000 wValue = 0x0000
wIndex = 0x0000 wIndex = 0x0000
wLength = 10 wLength = 10
``` ```
### EP0 Payload Layout ### EP0 Payload Layout
| Byte | Content | Encoding | | Byte | Content | Encoding |
|------|---------|----------| |------|---------|----------|
| [0] | Symbol Rate byte 0 | Little-endian LSB | | [0] | Symbol Rate byte 0 | Little-endian LSB |
| [1] | Symbol Rate byte 1 | | | [1] | Symbol Rate byte 1 | |
| [2] | Symbol Rate byte 2 | | | [2] | Symbol Rate byte 2 | |
| [3] | Symbol Rate byte 3 | Little-endian MSB | | [3] | Symbol Rate byte 3 | Little-endian MSB |
| [4] | Frequency byte 0 | Little-endian LSB | | [4] | Frequency byte 0 | Little-endian LSB |
| [5] | Frequency byte 1 | | | [5] | Frequency byte 1 | |
| [6] | Frequency byte 2 | | | [6] | Frequency byte 2 | |
| [7] | Frequency byte 3 | Little-endian MSB | | [7] | Frequency byte 3 | Little-endian MSB |
| [8] | Modulation Type | 0--9 (see table below) | | [8] | Modulation Type | 0--9 (see table below) |
| [9] | Inner FEC Rate | Index into modulation-specific table | | [9] | Inner FEC Rate | Index into modulation-specific table |
**Symbol Rate** is in samples per second (sps). The Windows driver converts from ksps: `ulTempSymbolRate = pDeviceParameter->ulSymbolRate * 1000`. Valid range: 256,000 -- 30,000,000 sps. **Symbol Rate** is in samples per second (sps). The Windows driver converts from ksps: `ulTempSymbolRate = pDeviceParameter->ulSymbolRate * 1000`. Valid range: 256,000 -- 30,000,000 sps.
**Frequency** is the IF frequency in kHz (950,000 -- 2,150,000), computed by the host as `(RF_freq - LO_freq) * multiplier`. **Frequency** is the IF frequency in kHz (950,000 -- 2,150,000), computed by the host as `(RF_freq - LO_freq) * multiplier`.
## Firmware Parameter Parsing ## Firmware Parameter Parsing
The firmware reads the 10-byte payload from EP0BUF (XRAM 0xE740--0xE749) and stores: The firmware reads the 10-byte payload from EP0BUF (XRAM 0xE740--0xE749) and stores:
| Source | Destination | Notes | | Source | Destination | Notes |
|--------|-------------|-------| |--------|-------------|-------|
| EP0BUF[8] (modulation) | IRAM 0x4D | Direct copy | | EP0BUF[8] (modulation) | IRAM 0x4D | Direct copy |
| EP0BUF[9] (FEC rate) | IRAM 0x4F | Direct copy | | EP0BUF[9] (FEC rate) | IRAM 0x4F | Direct copy |
| EP0BUF[4--7] (frequency) | XRAM 0xE0DB--0xE0DE | Byte-reversed (LE to BE) | | EP0BUF[4--7] (frequency) | XRAM 0xE0DB--0xE0DE | Byte-reversed (LE to BE) |
| EP0BUF[0--3] (symbol rate) | XRAM 0xE0CB--0xE0CE | Byte-reversed (LE to BE) | | EP0BUF[0--3] (symbol rate) | XRAM 0xE0CB--0xE0CE | Byte-reversed (LE to BE) |
The byte reversal converts host little-endian to BCM4500 big-endian, allowing values to be written directly to the demodulator via I2C without further conversion. The byte reversal converts host little-endian to BCM4500 big-endian, allowing values to be written directly to the demodulator via I2C without further conversion.
```asm title="EP0BUF Read (Rev.2 at CODE:0802)" ```asm title="EP0BUF Read (Rev.2 at CODE:0802)"
; Read modulation type and FEC rate ; Read modulation type and FEC rate
MOV DPTR, #0xE748 ; EP0BUF[8] = modulation type MOV DPTR, #0xE748 ; EP0BUF[8] = modulation type
MOVX A, @DPTR MOVX A, @DPTR
MOV 0x4D, A ; Store to IRAM 0x4D MOV 0x4D, A ; Store to IRAM 0x4D
INC DPTR ; DPTR = 0xE749 INC DPTR ; DPTR = 0xE749
MOVX A, @DPTR ; EP0BUF[9] = FEC rate MOVX A, @DPTR ; EP0BUF[9] = FEC rate
MOV 0x4F, A ; Store to IRAM 0x4F MOV 0x4F, A ; Store to IRAM 0x4F
``` ```
## Modulation Dispatch ## Modulation Dispatch
After parsing, the firmware validates the modulation type (bounds check against 10) and dispatches via a 20-byte jump table (10 entries x 2 bytes) at CODE:0873. Values >= 10 are rejected silently. After parsing, the firmware validates the modulation type (bounds check against 10) and dispatches via a 20-byte jump table (10 entries x 2 bytes) at CODE:0873. Values >= 10 are rejected silently.
### Dispatch Table (Rev.2) ### Dispatch Table (Rev.2)
| Entry | Target | Modulation | | Entry | Target | Modulation |
|-------|--------|-----------| |-------|--------|-----------|
| 0 | 0x08B7 | DVB-S QPSK | | 0 | 0x08B7 | DVB-S QPSK |
| 1 | 0x08DF | Turbo QPSK | | 1 | 0x08DF | Turbo QPSK |
| 2 | 0x08FA | Turbo 8PSK | | 2 | 0x08FA | Turbo 8PSK |
| 3 | 0x0915 | Turbo 16QAM | | 3 | 0x0915 | Turbo 16QAM |
| 4 | 0x0947 | DCII Combo | | 4 | 0x0947 | DCII Combo |
| 5 | 0x094F | DCII I-stream | | 5 | 0x094F | DCII I-stream |
| 6 | 0x0957 | DCII Q-stream | | 6 | 0x0957 | DCII Q-stream |
| 7 | 0x095F | DCII Offset QPSK | | 7 | 0x095F | DCII Offset QPSK |
| 8 | 0x0887 | DSS QPSK | | 8 | 0x0887 | DSS QPSK |
| 9 | 0x0887 | DVB BPSK (shares DSS handler) | | 9 | 0x0887 | DVB BPSK (shares DSS handler) |
Each handler validates the FEC index, looks up a preconfigured byte from an XRAM table, and writes configuration to four XRAM registers. Each handler validates the FEC index, looks up a preconfigured byte from an XRAM table, and writes configuration to four XRAM registers.
## Modulation Handler Details ## Modulation Handler Details
<Tabs> <Tabs>
<TabItem label="DVB-S / DSS / BPSK"> <TabItem label="DVB-S / DSS / BPSK">
### DVB-S QPSK (Index 0) ### DVB-S QPSK (Index 0)
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| FEC table base | XRAM 0xE0F9 | | FEC table base | XRAM 0xE0F9 |
| Max FEC index | 7 | | Max FEC index | 7 |
| Modulation type register | 0x09 | | Modulation type register | 0x09 |
| Turbo flag | 0x00 (off) | | Turbo flag | 0x00 (off) |
| Demod mode | 0x10 (standard) | | Demod mode | 0x10 (standard) |
| bmDCtuned | Cleared | | bmDCtuned | Cleared |
**FEC rates available** (table at 0xE0F9): 1/2, 2/3, 3/4, 5/6, 7/8, auto, none. **FEC rates available** (table at 0xE0F9): 1/2, 2/3, 3/4, 5/6, 7/8, auto, none.
### DSS QPSK (Index 8) and DVB-S BPSK (Index 9) ### DSS QPSK (Index 8) and DVB-S BPSK (Index 9)
DSS and DVB BPSK share the same handler at 0x0887. They use the same FEC table as DVB-S QPSK (0xE0F9) but OR the lookup value with 0x80 to distinguish them: DSS and DVB BPSK share the same handler at 0x0887. They use the same FEC table as DVB-S QPSK (0xE0F9) but OR the lookup value with 0x80 to distinguish them:
```c title="DSS/BPSK FEC Encoding" ```c title="DSS/BPSK FEC Encoding"
XRAM[0xE0EB] = XRAM[0xE0F9 + FEC_index] | 0x80; XRAM[0xE0EB] = XRAM[0xE0F9 + FEC_index] | 0x80;
// Out-of-range default: 0x8C // Out-of-range default: 0x8C
``` ```
</TabItem> </TabItem>
<TabItem label="Turbo Modes"> <TabItem label="Turbo Modes">
### Turbo QPSK (Index 1) ### Turbo QPSK (Index 1)
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| FEC table base | XRAM 0xE0B7 | | FEC table base | XRAM 0xE0B7 |
| Max FEC index | 5 | | Max FEC index | 5 |
| Modulation type register | 0x09 | | Modulation type register | 0x09 |
| Turbo flag | 0x01 (on) | | Turbo flag | 0x01 (on) |
| Demod mode | 0x10 | | Demod mode | 0x10 |
| bmDCtuned | Cleared | | bmDCtuned | Cleared |
### Turbo 8PSK (Index 2) ### Turbo 8PSK (Index 2)
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| FEC table base | XRAM 0xE0B1 | | FEC table base | XRAM 0xE0B1 |
| Max FEC index | 5 | | Max FEC index | 5 |
| Modulation type register | 0x09 | | Modulation type register | 0x09 |
| Turbo flag | 0x01 (on) | | Turbo flag | 0x01 (on) |
| Demod mode | 0x10 | | Demod mode | 0x10 |
| bmDCtuned | Cleared | | bmDCtuned | Cleared |
### Turbo 16QAM (Index 3) ### Turbo 16QAM (Index 3)
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| FEC table base | XRAM 0xE0BC | | FEC table base | XRAM 0xE0BC |
| Max FEC index | 1 | | Max FEC index | 1 |
| Modulation type register | 0x09 | | Modulation type register | 0x09 |
| Turbo flag | 0x01 (on) | | Turbo flag | 0x01 (on) |
| Demod mode | 0x10 | | Demod mode | 0x10 |
| bmDCtuned | Cleared | | bmDCtuned | Cleared |
</TabItem> </TabItem>
<TabItem label="DCII Modes"> <TabItem label="DCII Modes">
All four DCII variants share a common post-processing path but set different demod mode values: All four DCII variants share a common post-processing path but set different demod mode values:
| Modulation | Index | Demod Mode (0xE0F5) | | Modulation | Index | Demod Mode (0xE0F5) |
|-----------|-------|---------------------| |-----------|-------|---------------------|
| DCII Combo | 4 | 0x10 | | DCII Combo | 4 | 0x10 |
| DCII Offset QPSK | 7 | 0x11 | | DCII Offset QPSK | 7 | 0x11 |
| DCII I-stream (split) | 5 | 0x12 | | DCII I-stream (split) | 5 | 0x12 |
| DCII Q-stream (split) | 6 | 0x16 | | DCII Q-stream (split) | 6 | 0x16 |
**Common DCII parameters:** **Common DCII parameters:**
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| FEC table base | XRAM 0xE0BD | | FEC table base | XRAM 0xE0BD |
| Max FEC index | 9 | | Max FEC index | 9 |
| FEC code rate register | 0xFC (fixed for all DCII) | | FEC code rate register | 0xFC (fixed for all DCII) |
| Turbo flag | 0x00 (off) | | Turbo flag | 0x00 (off) |
| bmDCtuned | **Set** (0x40 OR'd into config status) | | bmDCtuned | **Set** (0x40 OR'd into config status) |
The DCII modulation type register (0xE0EC) is loaded from the lookup table at `0xE0BD + FEC_index`, unlike other modulations which use the fixed value 0x09. The DCII modulation type register (0xE0EC) is loaded from the lookup table at `0xE0BD + FEC_index`, unlike other modulations which use the fixed value 0x09.
</TabItem> </TabItem>
</Tabs> </Tabs>
## XRAM Configuration Summary ## XRAM Configuration Summary
After modulation dispatch, four XRAM registers hold the BCM4500 configuration: After modulation dispatch, four XRAM registers hold the BCM4500 configuration:
| XRAM Address | Register Name | DVB-S QPSK | Turbo (Q/8/16) | DCII | DSS/BPSK | | XRAM Address | Register Name | DVB-S QPSK | Turbo (Q/8/16) | DCII | DSS/BPSK |
|-------------|---------------|-----------|---------------|------|----------| |-------------|---------------|-----------|---------------|------|----------|
| 0xE0EB | FEC Code Rate | Table lookup | Table lookup | 0xFC (fixed) | Lookup OR 0x80 | | 0xE0EB | FEC Code Rate | Table lookup | Table lookup | 0xFC (fixed) | Lookup OR 0x80 |
| 0xE0EC | Modulation Type | 0x09 | 0x09 | From DCII table | 0x09 | | 0xE0EC | Modulation Type | 0x09 | 0x09 | From DCII table | 0x09 |
| 0xE0F5 | Demod Mode | 0x10 | 0x10 | 0x10/0x11/0x12/0x16 | 0x10 | | 0xE0F5 | Demod Mode | 0x10 | 0x10 | 0x10/0x11/0x12/0x16 | 0x10 |
| 0xE0F6 | Turbo Flag | 0x00 | 0x01 | 0x00 | 0x00 | | 0xE0F6 | Turbo Flag | 0x00 | 0x01 | 0x00 | 0x00 |
## FEC Rate Lookup Tables ## FEC Rate Lookup Tables
These tables are populated at boot from the CODE-space init table: These tables are populated at boot from the CODE-space init table:
| XRAM Base | Modulation | Max Index | Code Rates | | XRAM Base | Modulation | Max Index | Code Rates |
|-----------|-----------|-----------|------------| |-----------|-----------|-----------|------------|
| 0xE0F9 | DVB-S QPSK, DSS, BPSK | 7 | 1/2, 2/3, 3/4, 5/6, 7/8, auto, none | | 0xE0F9 | DVB-S QPSK, DSS, BPSK | 7 | 1/2, 2/3, 3/4, 5/6, 7/8, auto, none |
| 0xE0B7 | Turbo QPSK | 5 | Turbo-specific rates | | 0xE0B7 | Turbo QPSK | 5 | Turbo-specific rates |
| 0xE0B1 | Turbo 8PSK | 5 | Turbo-specific rates | | 0xE0B1 | Turbo 8PSK | 5 | Turbo-specific rates |
| 0xE0BC | Turbo 16QAM | 1 | Single code rate | | 0xE0BC | Turbo 16QAM | 1 | Single code rate |
| 0xE0BD | DCII (all variants) | 9 | Combined code + modulation | | 0xE0BD | DCII (all variants) | 9 | Combined code + modulation |
## Complete Tuning Sequence ## Complete Tuning Sequence
The full sequence from host command to signal acquisition: The full sequence from host command to signal acquisition:
<Steps> <Steps>
1. **LNB Configuration** (separate vendor commands, before TUNE_8PSK) 1. **LNB Configuration** (separate vendor commands, before TUNE_8PSK)
- SET_LNB_VOLTAGE (0x8B): GPIO P0.4, no I2C. wValue=1 for 18V (H/Circular-L), wValue=0 for 13V (V/Circular-R). - SET_LNB_VOLTAGE (0x8B): GPIO P0.4, no I2C. wValue=1 for 18V (H/Circular-L), wValue=0 for 13V (V/Circular-R).
- SET_22KHZ_TONE (0x8C): GPIO P0.3, no I2C. wValue=1 for high band, wValue=0 for low band. - SET_22KHZ_TONE (0x8C): GPIO P0.3, no I2C. wValue=1 for high band, wValue=0 for low band.
- SEND_DISEQC_COMMAND (0x8D): If multi-switch is needed. - SEND_DISEQC_COMMAND (0x8D): If multi-switch is needed.
2. **TUNE_8PSK (0x86)** -- Host sends 10-byte payload via USB control transfer. 2. **TUNE_8PSK (0x86)** -- Host sends 10-byte payload via USB control transfer.
3. **EP0BUF Parsing** -- Firmware reads modulation/FEC to IRAM, byte-reverses frequency/symbol rate to XRAM. 3. **EP0BUF Parsing** -- Firmware reads modulation/FEC to IRAM, byte-reverses frequency/symbol rate to XRAM.
4. **Modulation Dispatch** -- FEC lookup via jump table, XRAM configuration registers set. 4. **Modulation Dispatch** -- FEC lookup via jump table, XRAM configuration registers set.
5. **GPIO P3.6** -- DVB mode select pin driven based on modulation type. 5. **GPIO P3.6** -- DVB mode select pin driven based on modulation type.
6. **BCM4500 I2C Programming** (3 outer retries, each trying up to 3 I2C addresses): 6. **BCM4500 I2C Programming** (3 outer retries, each trying up to 3 I2C addresses):
- Poll BCM4500 ready: I2C READ registers 0xA2, 0xA8, 0xA4. - Poll BCM4500 ready: I2C READ registers 0xA2, 0xA8, 0xA4.
- Write page: I2C WRITE register 0xA6 with 0x00. - Write page: I2C WRITE register 0xA6 with 0x00.
- Write config data: I2C WRITE register 0xA7 with frequency, symbol rate, FEC, modulation, and demod parameters. - Write config data: I2C WRITE register 0xA7 with frequency, symbol rate, FEC, modulation, and demod parameters.
- Execute: I2C WRITE register 0xA8 with 0x03 (indirect write command). - Execute: I2C WRITE register 0xA8 with 0x03 (indirect write command).
- Poll completion: I2C READ registers 0xA8, 0xA2. - Poll completion: I2C READ registers 0xA8, 0xA2.
- Verify: I2C READ register 0xA7 (read-back compare). - Verify: I2C READ register 0xA7 (read-back compare).
7. **Signal Acquisition** (host polling): 7. **Signal Acquisition** (host polling):
- GET_SIGNAL_LOCK (0x90): Poll until non-zero. - GET_SIGNAL_LOCK (0x90): Poll until non-zero.
- GET_SIGNAL_STRENGTH (0x87): Read [SNR value](/bcm4500/signal-monitoring/). - GET_SIGNAL_STRENGTH (0x87): Read [SNR value](/bcm4500/signal-monitoring/).
</Steps> </Steps>
## I2C Programming Details ## I2C Programming Details
The core I2C write function (`FUN_CODE_1670` on Rev.2) implements the [BCM4500 indirect register protocol](/bcm4500/demodulator/): The core I2C write function (`FUN_CODE_1670` on Rev.2) implements the [BCM4500 indirect register protocol](/bcm4500/demodulator/):
```c title="BCM4500 Indirect Write (Decompiled)" ```c title="BCM4500 Indirect Write (Decompiled)"
void bcm4500_indirect_write(byte *data, byte count) { void bcm4500_indirect_write(byte *data, byte count) {
// Wait for BCM4500 ready (poll regs 0xA2, 0xA8, 0xA4) // Wait for BCM4500 ready (poll regs 0xA2, 0xA8, 0xA4)
bus_wait_ready(); bus_wait_ready();
// Write page address (0x00) to register 0xA6 // Write page address (0x00) to register 0xA6
i2c_write(1, 0, 0xA6, 0x10); // [0x00] i2c_write(1, 0, 0xA6, 0x10); // [0x00]
// Write data to register 0xA7 // Write data to register 0xA7
i2c_write(count, 0, 0xA7, 0x10); // [data0..dataN] i2c_write(count, 0, 0xA7, 0x10); // [data0..dataN]
// Write command (0x03 = indirect write) to 0xA8 // Write command (0x03 = indirect write) to 0xA8
i2c_write(1, 0, 0xA8, 0x10); // [0x03] i2c_write(1, 0, 0xA8, 0x10); // [0x03]
// Poll completion (regs 0xA8, 0xA2) // Poll completion (regs 0xA8, 0xA2)
poll_write_complete(); poll_write_complete();
// Verify: read back from 0xA7 and compare // Verify: read back from 0xA7 and compare
verify_readback(); verify_readback();
} }
``` ```
The demod scan function (`FUN_CODE_1dd0`) wraps this in a 3-address iteration loop, supporting hardware variants where the BCM4500 may respond at different I2C addresses. The outer tune function retries the entire scan up to 3 times. The demod scan function (`FUN_CODE_1dd0`) wraps this in a 3-address iteration loop, supporting hardware variants where the BCM4500 may respond at different I2C addresses. The outer tune function retries the entire scan up to 3 times.
<Aside type="note" title="Version Differences"> <Aside type="note" title="Version Differences">
The tuning logic is functionally identical across all three firmware versions. Differences are limited to code addresses (due to recompilation), the config status byte IRAM location, and minor implementation details in the signal strength polling path. v2.13 adds a 20-attempt retry loop with checksum verification on the I2C programming step. The tuning logic is functionally identical across all three firmware versions. Differences are limited to code addresses (due to recompilation), the config status byte IRAM location, and minor implementation details in the signal strength polling path. v2.13 adds a 20-attempt retry loop with checksum verification on the I2C programming step.
</Aside> </Aside>

View File

@ -1,169 +1,169 @@
--- ---
title: DVB-S2 Incompatibility title: DVB-S2 Incompatibility
description: Why the SkyWalker-1 cannot support DVB-S2 and what the BCM4500 demodulator actually provides. description: Why the SkyWalker-1 cannot support DVB-S2 and what the BCM4500 demodulator actually provides.
--- ---
import { Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components'; import { Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components';
<Aside type="danger"> <Aside type="danger">
**DVB-S2 is not supported on the SkyWalker-1.** This is a fundamental hardware limitation of the Broadcom BCM4500 demodulator silicon, not a firmware limitation. No firmware update can add DVB-S2 capability. The BCM4500 was designed and fabricated before the DVB-S2 standard was ratified (March 2005) and contains no LDPC or BCH decoder hardware. **DVB-S2 is not supported on the SkyWalker-1.** This is a fundamental hardware limitation of the Broadcom BCM4500 demodulator silicon, not a firmware limitation. No firmware update can add DVB-S2 capability. The BCM4500 was designed and fabricated before the DVB-S2 standard was ratified (March 2005) and contains no LDPC or BCH decoder hardware.
</Aside> </Aside>
## The Core Problem ## The Core Problem
DVB-S2 (ETSI EN 302 307) requires two forward error correction technologies that do not exist in the BCM4500: DVB-S2 (ETSI EN 302 307) requires two forward error correction technologies that do not exist in the BCM4500:
| FEC Component | BCM4500 Has | DVB-S2 Requires | | FEC Component | BCM4500 Has | DVB-S2 Requires |
|---------------|-------------|-----------------| |---------------|-------------|-----------------|
| Inner code | Viterbi (convolutional) + Turbo | **LDPC** (Low-Density Parity-Check) | | Inner code | Viterbi (convolutional) + Turbo | **LDPC** (Low-Density Parity-Check) |
| Outer code | Reed-Solomon (t=10) | **BCH** (Bose-Chaudhuri-Hocquenghem) | | Outer code | Reed-Solomon (t=10) | **BCH** (Bose-Chaudhuri-Hocquenghem) |
| Block size | Streaming (Viterbi) or short turbo blocks | **64,800 or 16,200 bits** | | Block size | Streaming (Viterbi) or short turbo blocks | **64,800 or 16,200 bits** |
| Decoder type | Trellis-based / iterative turbo | **Iterative belief propagation** | | Decoder type | Trellis-based / iterative turbo | **Iterative belief propagation** |
LDPC decoding requires dedicated silicon: large block RAM for message passing (the LDPC block is 64,800 bits), iterative belief propagation logic, and a fundamentally different decoder architecture. This cannot be emulated in firmware on the BCM4500's simple 8-bit on-chip microcontroller, which handles only configuration, acquisition, and monitoring -- not data-path processing. LDPC decoding requires dedicated silicon: large block RAM for message passing (the LDPC block is 64,800 bits), iterative belief propagation logic, and a fundamentally different decoder architecture. This cannot be emulated in firmware on the BCM4500's simple 8-bit on-chip microcontroller, which handles only configuration, acquisition, and monitoring -- not data-path processing.
## BCM4500 FEC Architecture ## BCM4500 FEC Architecture
The BCM4500 contains exactly two FEC decoder paths (from the [BCM4500 datasheet](https://elcodis.com/parts/5786421/BCM4500.html)): The BCM4500 contains exactly two FEC decoder paths (from the [BCM4500 datasheet](https://elcodis.com/parts/5786421/BCM4500.html)):
<Tabs> <Tabs>
<TabItem label="Legacy FEC"> <TabItem label="Legacy FEC">
### Viterbi + Reed-Solomon (Legacy) ### Viterbi + Reed-Solomon (Legacy)
Used for DVB-S QPSK, DSS QPSK, DVB-S BPSK, and Digicipher II modes. Used for DVB-S QPSK, DSS QPSK, DVB-S BPSK, and Digicipher II modes.
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| Inner decoder | Viterbi (convolutional) | | Inner decoder | Viterbi (convolutional) |
| Code rates | 1/2, 2/3, 3/4, 5/6, 7/8 | | Code rates | 1/2, 2/3, 3/4, 5/6, 7/8 |
| Outer decoder | Reed-Solomon | | Outer decoder | Reed-Solomon |
| Signal path | Soft decisions fed to Viterbi, then RS outer code | | Signal path | Soft decisions fed to Viterbi, then RS outer code |
| Modulations | BPSK, QPSK | | Modulations | BPSK, QPSK |
**Firmware evidence** (XRAM 0xE0F9): FEC lookup table with max index 7. Modulation dispatch sets `XRAM 0xE0F6 = 0x00` (turbo flag OFF), `XRAM 0xE0F5 = 0x10` (standard demod mode). **Firmware evidence** (XRAM 0xE0F9): FEC lookup table with max index 7. Modulation dispatch sets `XRAM 0xE0F6 = 0x00` (turbo flag OFF), `XRAM 0xE0F5 = 0x10` (standard demod mode).
**Windows driver**: `m_CurResource.ulInnerFecType = BDA_FEC_VITERBI` -- explicitly rejects any FEC type other than Viterbi. **Windows driver**: `m_CurResource.ulInnerFecType = BDA_FEC_VITERBI` -- explicitly rejects any FEC type other than Viterbi.
</TabItem> </TabItem>
<TabItem label="Turbo FEC"> <TabItem label="Turbo FEC">
### Turbo Code Decoder (Proprietary) ### Turbo Code Decoder (Proprietary)
Used for Turbo QPSK, Turbo 8PSK, and Turbo 16QAM -- proprietary "advanced modulation" modes developed by Broadcom for EchoStar/Dish Network. Used for Turbo QPSK, Turbo 8PSK, and Turbo 16QAM -- proprietary "advanced modulation" modes developed by Broadcom for EchoStar/Dish Network.
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| Inner decoder | Iterative turbo code | | Inner decoder | Iterative turbo code |
| QPSK rates | 1/4, 1/2, 3/4 | | QPSK rates | 1/4, 1/2, 3/4 |
| 8PSK rates | 2/3, 3/4, 5/6, 8/9 | | 8PSK rates | 2/3, 3/4, 5/6, 8/9 |
| 16QAM rates | 3/4 | | 16QAM rates | 3/4 |
| Outer decoder | Reed-Solomon (t=10) | | Outer decoder | Reed-Solomon (t=10) |
| Modulations | QPSK, 8PSK, 16QAM | | Modulations | QPSK, 8PSK, 16QAM |
**Firmware evidence** (XRAM 0xE0B7, 0xE0B1, 0xE0BC): Turbo FEC lookup tables. All turbo modes set `XRAM 0xE0F6 = 0x01` (turbo flag ON). **Firmware evidence** (XRAM 0xE0B7, 0xE0B1, 0xE0BC): Turbo FEC lookup tables. All turbo modes set `XRAM 0xE0F6 = 0x01` (turbo flag ON).
These turbo codes are NOT the same as DVB-S2's LDPC codes. The turbo decoder uses parallel concatenated convolutional codes, while LDPC uses sparse parity-check matrix belief propagation. Different algorithms, different silicon. These turbo codes are NOT the same as DVB-S2's LDPC codes. The turbo decoder uses parallel concatenated convolutional codes, while LDPC uses sparse parity-check matrix belief propagation. Different algorithms, different silicon.
</TabItem> </TabItem>
<TabItem label="Digicipher II"> <TabItem label="Digicipher II">
### DCII Decoder ### DCII Decoder
Used for DCII combo, split I/Q, and offset QPSK modes. Used for DCII combo, split I/Q, and offset QPSK modes.
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| FEC table | XRAM 0xE0BD, max index 9 | | FEC table | XRAM 0xE0BD, max index 9 |
| Fixed FEC code | `0xFC` written to XRAM 0xE0EB | | Fixed FEC code | `0xFC` written to XRAM 0xE0EB |
| Modulations | QPSK variants (combo, split, offset) | | Modulations | QPSK variants (combo, split, offset) |
</TabItem> </TabItem>
</Tabs> </Tabs>
The BCM4500 datasheet states explicitly: "Optimized soft decisions are then fed into either a DVB/DIRECTV/DCII-compliant FEC decoder, or an advanced modulation turbo decoder." These are the only two FEC paths. There is no third path for LDPC/BCH. The BCM4500 datasheet states explicitly: "Optimized soft decisions are then fed into either a DVB/DIRECTV/DCII-compliant FEC decoder, or an advanced modulation turbo decoder." These are the only two FEC paths. There is no third path for LDPC/BCH.
## Zero DVB-S2 Evidence in Firmware or Driver ## Zero DVB-S2 Evidence in Firmware or Driver
Exhaustive search across all firmware versions and Windows driver source: Exhaustive search across all firmware versions and Windows driver source:
| What Was Searched | Result | | What Was Searched | Result |
|-------------------|--------| |-------------------|--------|
| All firmware binaries (v2.06, Rev.2, v2.13) via Ghidra | No LDPC/BCH/DVB-S2 references | | All firmware binaries (v2.06, Rev.2, v2.13) via Ghidra | No LDPC/BCH/DVB-S2 references |
| Windows driver `SkyWalker1Control.h` | Modulation constants 0--9 only, none for DVB-S2 | | Windows driver `SkyWalker1Control.h` | Modulation constants 0--9 only, none for DVB-S2 |
| Windows driver `SkyWalker1TunerFilter.cpp` | Rejects non-Viterbi FEC types | | Windows driver `SkyWalker1TunerFilter.cpp` | Rejects non-Viterbi FEC types |
| Windows driver `SkyWalker1Control.cpp` | Hardcodes `ADV_MOD_DVB_QPSK` (value 0) | | Windows driver `SkyWalker1Control.cpp` | Hardcodes `ADV_MOD_DVB_QPSK` (value 0) |
| Firmware dispatch table (CODE:0873) | 10 entries max, values >= 10 rejected | | Firmware dispatch table (CODE:0873) | 10 entries max, values >= 10 rejected |
| All FEC lookup tables in XRAM | Only Viterbi rates and turbo rates, no LDPC rates | | All FEC lookup tables in XRAM | Only Viterbi rates and turbo rates, no LDPC rates |
| I2C register addresses | BCM4500-specific protocol only (page 0x00, regs 0xA6/A7/A8) | | I2C register addresses | BCM4500-specific protocol only (page 0x00, regs 0xA6/A7/A8) |
**Specific proof points:** **Specific proof points:**
- `SkyWalker1TunerFilter.cpp`, line 1070: `if(ulNewInnerFecType == BDA_FEC_VITERBI)` -- only Viterbi accepted; any other FEC type returns `STATUS_INVALID_PARAMETER` - `SkyWalker1TunerFilter.cpp`, line 1070: `if(ulNewInnerFecType == BDA_FEC_VITERBI)` -- only Viterbi accepted; any other FEC type returns `STATUS_INVALID_PARAMETER`
- `SkyWalker1Control.cpp`, line 292: `ucCommand[8] = ADV_MOD_DVB_QPSK;` -- always sends modulation type 0 - `SkyWalker1Control.cpp`, line 292: `ucCommand[8] = ADV_MOD_DVB_QPSK;` -- always sends modulation type 0
- Firmware jump table at CODE:0866: bounds check rejects modulation values >= 10 - Firmware jump table at CODE:0866: bounds check rejects modulation values >= 10
## Is the USB Data Path a Bottleneck? ## Is the USB Data Path a Bottleneck?
**No.** The GPIF/USB 2.0 streaming architecture has roughly 5x headroom for DVB-S2 data rates. The bottleneck is the demodulator silicon, not the transport path. **No.** The GPIF/USB 2.0 streaming architecture has roughly 5x headroom for DVB-S2 data rates. The bottleneck is the demodulator silicon, not the transport path.
| Metric | Value | | Metric | Value |
|--------|-------| |--------|-------|
| DVB-S2 max net rate (8PSK 9/10, 30 Msps) | ~58 Mbps (~7.25 MB/s) | | DVB-S2 max net rate (8PSK 9/10, 30 Msps) | ~58 Mbps (~7.25 MB/s) |
| Typical HD transponder (8PSK 3/4, 27.5 Msps) | ~44 Mbps | | Typical HD transponder (8PSK 3/4, 27.5 Msps) | ~44 Mbps |
| USB 2.0 practical bulk throughput | ~280 Mbps (~35 MB/s) | | USB 2.0 practical bulk throughput | ~280 Mbps (~35 MB/s) |
| GPIF engine theoretical throughput (48 MHz, 8-bit) | 384 Mbps (48 MB/s) | | GPIF engine theoretical throughput (48 MHz, 8-bit) | 384 Mbps (48 MB/s) |
| Current DVB-S typical TS rate | 1--5 MB/s | | Current DVB-S typical TS rate | 1--5 MB/s |
DVB-S2 uses the same MPEG-TS output format (188-byte packets) as DVB-S, so the GPIF waveform and AUTOIN configuration would work unchanged. DVB-S2 uses the same MPEG-TS output format (188-byte packets) as DVB-S, so the GPIF waveform and AUTOIN configuration would work unchanged.
However, this is a moot point: even if the BCM4500 were physically replaced with a DVB-S2-capable chip, the entire FX2 firmware would need rewriting (I2C register protocol, tuning sequence, modulation dispatch, FEC configuration), since every DVB-S2 demodulator uses a completely different register interface. However, this is a moot point: even if the BCM4500 were physically replaced with a DVB-S2-capable chip, the entire FX2 firmware would need rewriting (I2C register protocol, tuning sequence, modulation dispatch, FEC configuration), since every DVB-S2 demodulator uses a completely different register interface.
## Broadcom's DVB-S2 Silicon Timeline ## Broadcom's DVB-S2 Silicon Timeline
Broadcom addressed DVB-S2 by designing entirely new chips -- they did not add LDPC to the BCM4500: Broadcom addressed DVB-S2 by designing entirely new chips -- they did not add LDPC to the BCM4500:
| Chip | Year | DVB-S2 | Key Addition | | Chip | Year | DVB-S2 | Key Addition |
|------|------|--------|-------------| |------|------|--------|-------------|
| **BCM4500** | ~2003 | No | Turbo FEC + Viterbi/RS | | **BCM4500** | ~2003 | No | Turbo FEC + Viterbi/RS |
| **BCM4501** | 2006 | **Yes** | First dual-tuner DVB-S2; LDPC/BCH decoder | | **BCM4501** | 2006 | **Yes** | First dual-tuner DVB-S2; LDPC/BCH decoder |
| **BCM4505** | 2007 | **Yes** | Single-channel, 65nm, LDPC/BCH + legacy | | **BCM4505** | 2007 | **Yes** | Single-channel, 65nm, LDPC/BCH + legacy |
| **BCM4506** | 2007 | **Yes** | Dual-channel, 65nm, LDPC/BCH + legacy | | **BCM4506** | 2007 | **Yes** | Dual-channel, 65nm, LDPC/BCH + legacy |
The BCM4501 datasheet explicitly states it includes "four 8-bit ADCs, all-digital variable rate QPSK/8PSK receivers, advanced modulation LDPC/BCH, and DVB-S-compliant forward error correction decoder." Adding LDPC/BCH required new silicon. The BCM4501 datasheet explicitly states it includes "four 8-bit ADCs, all-digital variable rate QPSK/8PSK receivers, advanced modulation LDPC/BCH, and DVB-S-compliant forward error correction decoder." Adding LDPC/BCH required new silicon.
<Aside type="note"> <Aside type="note">
Broadcom restricted sales of the BCM4501/4505/4506 to set-top box manufacturers (EchoStar, DIRECTV). They did not sell to PC peripheral makers. This is why Genpix could not simply drop in a BCM4501 as a replacement. Broadcom restricted sales of the BCM4501/4505/4506 to set-top box manufacturers (EchoStar, DIRECTV). They did not sell to PC peripheral makers. This is why Genpix could not simply drop in a BCM4501 as a replacement.
</Aside> </Aside>
## What Genpix Did: The SkyWalker-3 ## What Genpix Did: The SkyWalker-3
Genpix released the SkyWalker-3 as a DVB-S2-capable successor using a completely different demodulator (likely STMicroelectronics STV0903): Genpix released the SkyWalker-3 as a DVB-S2-capable successor using a completely different demodulator (likely STMicroelectronics STV0903):
| Feature | SkyWalker-1 (BCM4500) | SkyWalker-3 (likely STV0903) | | Feature | SkyWalker-1 (BCM4500) | SkyWalker-3 (likely STV0903) |
|---------|----------------------|---------------------------| |---------|----------------------|---------------------------|
| DVB-S QPSK | Yes | Yes | | DVB-S QPSK | Yes | Yes |
| DVB-S2 QPSK | **No** | Yes | | DVB-S2 QPSK | **No** | Yes |
| DVB-S2 8PSK | **No** | Yes | | DVB-S2 8PSK | **No** | Yes |
| Turbo QPSK | Yes | **No** | | Turbo QPSK | Yes | **No** |
| Turbo 8PSK | Yes | **No** | | Turbo 8PSK | Yes | **No** |
| Turbo 16QAM | Yes | **No** | | Turbo 16QAM | Yes | **No** |
| DCII | Yes | Yes | | DCII | Yes | Yes |
| DSS | Yes | Yes | | DSS | Yes | Yes |
| Symbol rate (DVB-S) | 256 Ksps -- 30 Msps | 1 -- 45 Msps | | Symbol rate (DVB-S) | 256 Ksps -- 30 Msps | 1 -- 45 Msps |
| Symbol rate (DVB-S2) | N/A | 5 -- 33 Msps | | Symbol rate (DVB-S2) | N/A | 5 -- 33 Msps |
| FEC inner (DVB-S) | Viterbi | Viterbi | | FEC inner (DVB-S) | Viterbi | Viterbi |
| FEC inner (DVB-S2) | N/A | LDPC | | FEC inner (DVB-S2) | N/A | LDPC |
| FEC outer (DVB-S2) | N/A | BCH | | FEC outer (DVB-S2) | N/A | BCH |
The trade-off is clear: the SkyWalker-3 gained DVB-S2 but **lost turbo-FEC support entirely**. The turbo codes were proprietary to Broadcom/EchoStar, and the STV0903 does not implement them. This means the SkyWalker-3 cannot receive Dish Network's legacy turbo-coded 8PSK transmissions. The trade-off is clear: the SkyWalker-3 gained DVB-S2 but **lost turbo-FEC support entirely**. The turbo codes were proprietary to Broadcom/EchoStar, and the STV0903 does not implement them. This means the SkyWalker-3 cannot receive Dish Network's legacy turbo-coded 8PSK transmissions.
## Summary ## Summary
| Question | Answer | | Question | Answer |
|----------|--------| |----------|--------|
| Is DVB-S2 a hardware or firmware limitation? | **Hardware** -- BCM4500 has no LDPC/BCH decoder | | Is DVB-S2 a hardware or firmware limitation? | **Hardware** -- BCM4500 has no LDPC/BCH decoder |
| Could a firmware update add DVB-S2? | **No** -- LDPC requires dedicated silicon | | Could a firmware update add DVB-S2? | **No** -- LDPC requires dedicated silicon |
| Which Broadcom chip first added LDPC? | **BCM4501** (2006) | | Which Broadcom chip first added LDPC? | **BCM4501** (2006) |
| Any DVB-S2 hints in firmware/driver? | **None** -- zero references anywhere | | Any DVB-S2 hints in firmware/driver? | **None** -- zero references anywhere |
| Is the USB data path a bottleneck? | **No** -- ~5x headroom for DVB-S2 rates | | Is the USB data path a bottleneck? | **No** -- ~5x headroom for DVB-S2 rates |
| What did Genpix do for DVB-S2? | Released SkyWalker-3 with STV0903 demodulator | | What did Genpix do for DVB-S2? | Released SkyWalker-3 with STV0903 demodulator |
| What was lost in the SkyWalker-3? | Turbo-FEC support (Broadcom/EchoStar proprietary) | | What was lost in the SkyWalker-3? | Turbo-FEC support (Broadcom/EchoStar proprietary) |

View File

@ -1,272 +1,272 @@
--- ---
title: Linux Kernel Driver title: Linux Kernel Driver
description: Architecture and command analysis of the dvb_usb_gp8psk kernel module for Genpix satellite receivers. description: Architecture and command analysis of the dvb_usb_gp8psk kernel module for Genpix satellite receivers.
--- ---
import { Steps, Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components'; import { Steps, Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components';
The `dvb_usb_gp8psk` module is a Linux kernel DVB-USB driver supporting multiple Genpix satellite receiver models. It communicates with the FX2 microcontroller via USB vendor control requests to manage tuning, demodulation, LNB control, DiSEqC switching, and transport stream capture. The `dvb_usb_gp8psk` module is a Linux kernel DVB-USB driver supporting multiple Genpix satellite receiver models. It communicates with the FX2 microcontroller via USB vendor control requests to manage tuning, demodulation, LNB control, DiSEqC switching, and transport stream capture.
**Source files**: `drivers/media/usb/dvb-usb/gp8psk.c`, `gp8psk.h`, `gp8psk-fe.c` **Source files**: `drivers/media/usb/dvb-usb/gp8psk.c`, `gp8psk.h`, `gp8psk-fe.c`
## USB Device Table ## USB Device Table
| USB ID | Device Name | cold_ids | warm_ids | FW01 Needed? | | USB ID | Device Name | cold_ids | warm_ids | FW01 Needed? |
|--------|-------------|----------|----------|-------------| |--------|-------------|----------|----------|-------------|
| `v09C0p0200` | Rev.1 Cold | Yes | -- | **Yes** | | `v09C0p0200` | Rev.1 Cold | Yes | -- | **Yes** |
| `v09C0p0201` | Rev.1 Warm | -- | Yes | No (FW02 needed) | | `v09C0p0201` | Rev.1 Warm | -- | Yes | No (FW02 needed) |
| `v09C0p0202` | Rev.2 | -- | Yes | No | | `v09C0p0202` | Rev.2 | -- | Yes | No |
| `v09C0p0203` | SkyWalker-1 | -- | Yes | No | | `v09C0p0203` | SkyWalker-1 | -- | Yes | No |
| `v09C0p0204` | SkyWalker-1 (alt) | -- | Yes | No | | `v09C0p0204` | SkyWalker-1 (alt) | -- | Yes | No |
| `v09C0p0206` | SkyWalker CW3K | -- | Yes | No | | `v09C0p0206` | SkyWalker CW3K | -- | Yes | No |
<Aside type="note"> <Aside type="note">
PID `0x0205` (SkyWalker-2) is absent from the kernel 6.16.5 build. PID `0x0203` was not present in earlier kernel versions (e.g., v6.6.1) -- it was added later as the SkyWalker-1 gained community attention. PID `0x0205` (SkyWalker-2) is absent from the kernel 6.16.5 build. PID `0x0203` was not present in earlier kernel versions (e.g., v6.6.1) -- it was added later as the SkyWalker-1 gained community attention.
</Aside> </Aside>
## Driver Architecture ## Driver Architecture
The driver consists of three source files: The driver consists of three source files:
| File | Purpose | | File | Purpose |
|------|---------| |------|---------|
| `gp8psk.c` | USB device management, firmware loading, power control, vendor command wrappers | | `gp8psk.c` | USB device management, firmware loading, power control, vendor command wrappers |
| `gp8psk.h` | Vendor command constants, firmware version thresholds, USB PID definitions | | `gp8psk.h` | Vendor command constants, firmware version thresholds, USB PID definitions |
| `gp8psk-fe.c` | DVB frontend implementation: tuning, signal monitoring, LNB/DiSEqC callbacks | | `gp8psk-fe.c` | DVB frontend implementation: tuning, signal monitoring, LNB/DiSEqC callbacks |
The driver registers with the DVB-USB framework (`dvb_usb_device_properties`) which handles: The driver registers with the DVB-USB framework (`dvb_usb_device_properties`) which handles:
- USB device enumeration and firmware download (for cold devices) - USB device enumeration and firmware download (for cold devices)
- DVB adapter and frontend creation - DVB adapter and frontend creation
- URB management for bulk transport stream capture - URB management for bulk transport stream capture
- Power management callbacks - Power management callbacks
## USB Transfer Parameters ## USB Transfer Parameters
```c title="Driver USB configuration" ```c title="Driver USB configuration"
gp8psk_properties { gp8psk_properties {
.usb_ctrl = CYPRESS_FX2; .usb_ctrl = CYPRESS_FX2;
.firmware = "dvb-usb-gp8psk-01.fw"; .firmware = "dvb-usb-gp8psk-01.fw";
.num_adapters = 1; .num_adapters = 1;
.generic_bulk_ctrl_endpoint = 0x01; .generic_bulk_ctrl_endpoint = 0x01;
// Streaming: // Streaming:
.endpoint = 0x82; // IN bulk .endpoint = 0x82; // IN bulk
.stream = USB_BULK; .stream = USB_BULK;
.count = 7; // URBs .count = 7; // URBs
.buffersize = 8192; // bytes per URB .buffersize = 8192; // bytes per URB
} }
``` ```
The driver allocates 7 URBs of 8192 bytes each (56 KB total) for transport stream reception on endpoint `0x82` (IN bulk). Vendor commands use endpoint `0x01` with a 2000 ms timeout. The driver allocates 7 URBs of 8192 bytes each (56 KB total) for transport stream reception on endpoint `0x82` (IN bulk). Vendor commands use endpoint `0x01` with a 2000 ms timeout.
### Retry Logic ### Retry Logic
IN operations retry up to 3 times if partial data is received. The command buffer is 80 bytes maximum: IN operations retry up to 3 times if partial data is received. The command buffer is 80 bytes maximum:
```c title="Vendor command wrapper" ```c title="Vendor command wrapper"
static int gp8psk_usb_in_op(struct dvb_usb_device *d, static int gp8psk_usb_in_op(struct dvb_usb_device *d,
u8 req, u16 value, u16 index, u8 *b, int blen) u8 req, u16 value, u16 index, u8 *b, int blen)
{ {
int ret; int ret;
int try; int try;
for (try = 0; try < 3; try++) { for (try = 0; try < 3; try++) {
ret = usb_control_msg(d->udev, ret = usb_control_msg(d->udev,
usb_rcvctrlpipe(d->udev, 0), usb_rcvctrlpipe(d->udev, 0),
req, USB_TYPE_VENDOR | USB_DIR_IN, req, USB_TYPE_VENDOR | USB_DIR_IN,
value, index, b, blen, 2000); value, index, b, blen, 2000);
if (ret == blen) break; if (ret == blen) break;
} }
return ret; return ret;
} }
``` ```
## Complete Vendor Command Map ## Complete Vendor Command Map
| Cmd | Name | Dir | wValue | wLength | Purpose | | Cmd | Name | Dir | wValue | wLength | Purpose |
|-----|------|-----|--------|---------|---------| |-----|------|-----|--------|---------|---------|
| `0x80` | GET_8PSK_CONFIG | IN | `0x0000` | 1 | Read config status byte | | `0x80` | GET_8PSK_CONFIG | IN | `0x0000` | 1 | Read config status byte |
| `0x81` | SET_8PSK_CONFIG | OUT | varies | 0 | STALL (not implemented) | | `0x81` | SET_8PSK_CONFIG | OUT | varies | 0 | STALL (not implemented) |
| `0x83` | I2C_WRITE | OUT | dev_addr | N | Write to BCM4500 via I2C | | `0x83` | I2C_WRITE | OUT | dev_addr | N | Write to BCM4500 via I2C |
| `0x84` | I2C_READ | IN | dev_addr | N | Read from BCM4500 via I2C | | `0x84` | I2C_READ | IN | dev_addr | N | Read from BCM4500 via I2C |
| `0x85` | ARM_TRANSFER | OUT | 0/1 | 0 | Start/stop TS streaming | | `0x85` | ARM_TRANSFER | OUT | 0/1 | 0 | Start/stop TS streaming |
| `0x86` | TUNE_8PSK | OUT | `0x0000` | 10 | Send tuning parameters | | `0x86` | TUNE_8PSK | OUT | `0x0000` | 10 | Send tuning parameters |
| `0x87` | GET_SIGNAL_STRENGTH | IN | `0x0000` | 6 | Read SNR values | | `0x87` | GET_SIGNAL_STRENGTH | IN | `0x0000` | 6 | Read SNR values |
| `0x88` | LOAD_BCM4500 | OUT | 1 | 0 | Initiate demod FW download | | `0x88` | LOAD_BCM4500 | OUT | 1 | 0 | Initiate demod FW download |
| `0x89` | BOOT_8PSK | IN | 0/1 | 1 | Power on/off demodulator | | `0x89` | BOOT_8PSK | IN | 0/1 | 1 | Power on/off demodulator |
| `0x8A` | START_INTERSIL | IN | 0/1 | 1 | Enable/disable LNB supply | | `0x8A` | START_INTERSIL | IN | 0/1 | 1 | Enable/disable LNB supply |
| `0x8B` | SET_LNB_VOLTAGE | OUT | 0/1 | 0 | Set 13V (0) or 18V (1) | | `0x8B` | SET_LNB_VOLTAGE | OUT | 0/1 | 0 | Set 13V (0) or 18V (1) |
| `0x8C` | SET_22KHZ_TONE | OUT | 0/1 | 0 | Enable/disable 22 kHz tone | | `0x8C` | SET_22KHZ_TONE | OUT | 0/1 | 0 | Enable/disable 22 kHz tone |
| `0x8D` | SEND_DISEQC | OUT | msg[0] | 3-6 | Send DiSEqC message | | `0x8D` | SEND_DISEQC | OUT | msg[0] | 3-6 | Send DiSEqC message |
| `0x8E` | SET_DVB_MODE | OUT | 1 | 0 | Enable DVB-S mode | | `0x8E` | SET_DVB_MODE | OUT | 1 | 0 | Enable DVB-S mode |
| `0x8F` | SET_DN_SWITCH | OUT | cmd | 0 | Legacy Dish switch command | | `0x8F` | SET_DN_SWITCH | OUT | cmd | 0 | Legacy Dish switch command |
| `0x90` | GET_SIGNAL_LOCK | IN | `0x0000` | 1 | Read lock status | | `0x90` | GET_SIGNAL_LOCK | IN | `0x0000` | 1 | Read lock status |
| `0x92` | GET_FW_VERS | IN | `0x0000` | 6 | Read firmware version | | `0x92` | GET_FW_VERS | IN | `0x0000` | 6 | Read firmware version |
| `0x94` | USE_EXTRA_VOLT | OUT | 0/1 | 0 | Enable +1V LNB boost | | `0x94` | USE_EXTRA_VOLT | OUT | 0/1 | 0 | Enable +1V LNB boost |
| `0x95` | GET_FPGA_VERS | IN | `0x0000` | 1 | Read hardware platform ID | | `0x95` | GET_FPGA_VERS | IN | `0x0000` | 1 | Read hardware platform ID |
| `0x99` | GET_DEMOD_STATUS | IN | `0x0000` | 1 | Read BCM4500 reg 0xF9 (v2.13+) | | `0x99` | GET_DEMOD_STATUS | IN | `0x0000` | 1 | Read BCM4500 reg 0xF9 (v2.13+) |
| `0x9A` | INIT_DEMOD | OUT | `0x0000` | 0 | Re-init demodulator (v2.13+) | | `0x9A` | INIT_DEMOD | OUT | `0x0000` | 0 | Re-init demodulator (v2.13+) |
| `0x9C` | DELAY_COMMAND | OUT | param | 0 | Tuning delay with polling (v2.13+) | | `0x9C` | DELAY_COMMAND | OUT | param | 0 | Tuning delay with polling (v2.13+) |
| `0x9D` | CW3K_INIT | OUT | 0/1 | 0 | CW3K model initialization | | `0x9D` | CW3K_INIT | OUT | 0/1 | 0 | CW3K model initialization |
## Configuration Status Byte ## Configuration Status Byte
`GET_8PSK_CONFIG` (`0x80`) returns a bit-mapped status register: `GET_8PSK_CONFIG` (`0x80`) returns a bit-mapped status register:
``` ```
Bit 0 (0x01): bm8pskStarted - Device booted and running Bit 0 (0x01): bm8pskStarted - Device booted and running
Bit 1 (0x02): bm8pskFW_Loaded - BCM4500 firmware loaded Bit 1 (0x02): bm8pskFW_Loaded - BCM4500 firmware loaded
Bit 2 (0x04): bmIntersilOn - LNB power supply enabled Bit 2 (0x04): bmIntersilOn - LNB power supply enabled
Bit 3 (0x08): bmDVBmode - DVB mode enabled Bit 3 (0x08): bmDVBmode - DVB mode enabled
Bit 4 (0x10): bm22kHz - 22 kHz tone active Bit 4 (0x10): bm22kHz - 22 kHz tone active
Bit 5 (0x20): bmSEL18V - 18V LNB voltage selected Bit 5 (0x20): bmSEL18V - 18V LNB voltage selected
Bit 6 (0x40): bmDCtuned - DC offset tuning complete Bit 6 (0x40): bmDCtuned - DC offset tuning complete
Bit 7 (0x80): bmArmed - MPEG-2 stream transfer armed Bit 7 (0x80): bmArmed - MPEG-2 stream transfer armed
``` ```
## Boot Sequence ## Boot Sequence
<Steps> <Steps>
1. **Read config** (`GET_8PSK_CONFIG 0x80`): Check bit 0 (`bm8pskStarted`) 1. **Read config** (`GET_8PSK_CONFIG 0x80`): Check bit 0 (`bm8pskStarted`)
2. **Boot device** if not started: Send `BOOT_8PSK 0x89` with `wValue=1`, then read firmware version via `GET_FW_VERS 0x92` 2. **Boot device** if not started: Send `BOOT_8PSK 0x89` with `wValue=1`, then read firmware version via `GET_FW_VERS 0x92`
3. **Load BCM4500 firmware** if bit 1 not set: Only for Rev.1 Warm (PID `0x0201`). Send `LOAD_BCM4500 0x88` followed by firmware chunks. Skipped for SkyWalker-1 (bit already set from EEPROM boot). 3. **Load BCM4500 firmware** if bit 1 not set: Only for Rev.1 Warm (PID `0x0201`). Send `LOAD_BCM4500 0x88` followed by firmware chunks. Skipped for SkyWalker-1 (bit already set from EEPROM boot).
4. **Enable LNB** if bit 2 not set: Send `START_INTERSIL 0x8A` with `wValue=1` 4. **Enable LNB** if bit 2 not set: Send `START_INTERSIL 0x8A` with `wValue=1`
5. **Set DVB mode**: Send `SET_DVB_MODE 0x8E` with `wValue=1` (STALL on some revisions) 5. **Set DVB mode**: Send `SET_DVB_MODE 0x8E` with `wValue=1` (STALL on some revisions)
6. **Cancel pending stream**: Send `ARM_TRANSFER 0x85` with `wValue=0` 6. **Cancel pending stream**: Send `ARM_TRANSFER 0x85` with `wValue=0`
7. **Ready for tuning** 7. **Ready for tuning**
</Steps> </Steps>
## Tuning Flow ## Tuning Flow
```c title="10-byte tuning payload" ```c title="10-byte tuning payload"
Bytes 0-3: Symbol Rate (u32 LE, in sps) Bytes 0-3: Symbol Rate (u32 LE, in sps)
Bytes 4-7: Frequency (u32 LE, in kHz) Bytes 4-7: Frequency (u32 LE, in kHz)
Byte 8: Modulation (0-9, see modulation types) Byte 8: Modulation (0-9, see modulation types)
Byte 9: FEC Rate (index into firmware FEC table) Byte 9: FEC Rate (index into firmware FEC table)
``` ```
### Modulation Types ### Modulation Types
| Value | Constant | Mode | | Value | Constant | Mode |
|-------|----------|------| |-------|----------|------|
| 0 | `ADV_MOD_DVB_QPSK` | DVB-S QPSK | | 0 | `ADV_MOD_DVB_QPSK` | DVB-S QPSK |
| 1 | `ADV_MOD_TURBO_QPSK` | Turbo QPSK | | 1 | `ADV_MOD_TURBO_QPSK` | Turbo QPSK |
| 2 | `ADV_MOD_TURBO_8PSK` | Turbo 8PSK | | 2 | `ADV_MOD_TURBO_8PSK` | Turbo 8PSK |
| 3 | `ADV_MOD_TURBO_16QAM` | Turbo 16QAM | | 3 | `ADV_MOD_TURBO_16QAM` | Turbo 16QAM |
| 4 | `ADV_MOD_DCII_C_QPSK` | Digicipher II Combo | | 4 | `ADV_MOD_DCII_C_QPSK` | Digicipher II Combo |
| 5 | `ADV_MOD_DCII_I_QPSK` | Digicipher II I-stream | | 5 | `ADV_MOD_DCII_I_QPSK` | Digicipher II I-stream |
| 6 | `ADV_MOD_DCII_Q_QPSK` | Digicipher II Q-stream | | 6 | `ADV_MOD_DCII_Q_QPSK` | Digicipher II Q-stream |
| 7 | `ADV_MOD_DCII_C_OQPSK` | Digicipher II Offset QPSK | | 7 | `ADV_MOD_DCII_C_OQPSK` | Digicipher II Offset QPSK |
| 8 | `ADV_MOD_DSS_QPSK` | DSS/DIRECTV QPSK | | 8 | `ADV_MOD_DSS_QPSK` | DSS/DIRECTV QPSK |
| 9 | `ADV_MOD_DVB_BPSK` | DVB-S BPSK | | 9 | `ADV_MOD_DVB_BPSK` | DVB-S BPSK |
### Signal Quality ### Signal Quality
`GET_SIGNAL_STRENGTH` (`0x87`) returns 6 bytes: `GET_SIGNAL_STRENGTH` (`0x87`) returns 6 bytes:
``` ```
Bytes 0-1: SNR value (u16 LE, in dBu*256 units) Bytes 0-1: SNR value (u16 LE, in dBu*256 units)
Bytes 2-5: Reserved / diagnostics Bytes 2-5: Reserved / diagnostics
``` ```
SNR scaling in the kernel: `snr_value * 17` maps to the 0--65535 range. 100% signal quality corresponds to SNR >= `0x0F00`. SNR scaling in the kernel: `snr_value * 17` maps to the 0--65535 range. 100% signal quality corresponds to SNR >= `0x0F00`.
## Firmware Version Handling ## Firmware Version Handling
The driver defines two version constants in `gp8psk-fe.h`: The driver defines two version constants in `gp8psk-fe.h`:
```c title="Firmware version thresholds" ```c title="Firmware version thresholds"
#define GP8PSK_FW_REV1 0x020604 // v2.06.4 #define GP8PSK_FW_REV1 0x020604 // v2.06.4
#define GP8PSK_FW_REV2 0x020704 // v2.07.4 #define GP8PSK_FW_REV2 0x020704 // v2.07.4
``` ```
<Tabs> <Tabs>
<TabItem label="< FW_REV1"> <TabItem label="< FW_REV1">
Oldest firmware. No extended commands available. Oldest firmware. No extended commands available.
</TabItem> </TabItem>
<TabItem label=">= FW_REV1"> <TabItem label=">= FW_REV1">
v2.06.4 baseline. All standard commands operational. Uses `GET_SIGNAL_STRENGTH` for BER monitoring. v2.06.4 baseline. All standard commands operational. Uses `GET_SIGNAL_STRENGTH` for BER monitoring.
</TabItem> </TabItem>
<TabItem label=">= FW_REV2"> <TabItem label=">= FW_REV2">
v2.07.4+. Enables additional code paths: v2.07.4+. Enables additional code paths:
- `GET_DEMOD_STATUS` (`0x99`) for demod health check - `GET_DEMOD_STATUS` (`0x99`) for demod health check
- `INIT_DEMOD` (`0x9A`) for demod re-initialization - `INIT_DEMOD` (`0x9A`) for demod re-initialization
- `DELAY_COMMAND` (`0x9C`) for tuning acquisition delays - `DELAY_COMMAND` (`0x9C`) for tuning acquisition delays
- Different signal quality calculation - Different signal quality calculation
</TabItem> </TabItem>
</Tabs> </Tabs>
## Command Correlation with Firmware ## Command Correlation with Firmware
Not all vendor commands work on all firmware versions. The STALL behavior varies: Not all vendor commands work on all firmware versions. The STALL behavior varies:
| Command | v2.06 FW | v2.13 FW | Rev.2 FW | Custom v3.01 | | Command | v2.06 FW | v2.13 FW | Rev.2 FW | Custom v3.01 |
|---------|----------|----------|----------|-------------| |---------|----------|----------|----------|-------------|
| `0x80` GET_8PSK_CONFIG | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | | `0x80` GET_8PSK_CONFIG | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
| `0x86` TUNE_8PSK | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | | `0x86` TUNE_8PSK | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
| `0x87` GET_SIGNAL_STRENGTH | <Badge text="OK" variant="success" /> | <Badge text="Changed" variant="caution" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | | `0x87` GET_SIGNAL_STRENGTH | <Badge text="OK" variant="success" /> | <Badge text="Changed" variant="caution" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
| `0x88` LOAD_BCM4500 | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> | | `0x88` LOAD_BCM4500 | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> |
| `0x99` GET_DEMOD_STATUS | <Badge text="STALL" variant="danger" /> | <Badge text="OK" variant="success" /> | <Badge text="Proto" variant="caution" /> | N/A | | `0x99` GET_DEMOD_STATUS | <Badge text="STALL" variant="danger" /> | <Badge text="OK" variant="success" /> | <Badge text="Proto" variant="caution" /> | N/A |
| `0x9A` INIT_DEMOD | <Badge text="STALL" variant="danger" /> | <Badge text="OK" variant="success" /> | <Badge text="Proto" variant="caution" /> | N/A | | `0x9A` INIT_DEMOD | <Badge text="STALL" variant="danger" /> | <Badge text="OK" variant="success" /> | <Badge text="Proto" variant="caution" /> | N/A |
| `0x9C` DELAY_COMMAND | <Badge text="STALL" variant="danger" /> | <Badge text="OK" variant="success" /> | N/A | N/A | | `0x9C` DELAY_COMMAND | <Badge text="STALL" variant="danger" /> | <Badge text="OK" variant="success" /> | N/A | N/A |
<Aside type="note"> <Aside type="note">
Command `0x88` (`LOAD_BCM4500`) routes to the STALL handler in **all** extracted firmware versions. The kernel only sends it for Rev.1 Warm devices (PID `0x0201`) after confirming `bm8pskFW_Loaded` is not set. On SkyWalker-1 hardware, the BCM4500 firmware is in ROM, so this bit is always set at boot. Command `0x88` (`LOAD_BCM4500`) routes to the STALL handler in **all** extracted firmware versions. The kernel only sends it for Rev.1 Warm devices (PID `0x0201`) after confirming `bm8pskFW_Loaded` is not set. On SkyWalker-1 hardware, the BCM4500 firmware is in ROM, so this bit is always set at boot.
</Aside> </Aside>
## Kernel Module Parameters ## Kernel Module Parameters
The gp8psk module inherits standard DVB-USB parameters: The gp8psk module inherits standard DVB-USB parameters:
| Parameter | Default | Description | | Parameter | Default | Description |
|-----------|---------|-------------| |-----------|---------|-------------|
| `debug` | 0 | Enable debug logging (bitmask) | | `debug` | 0 | Enable debug logging (bitmask) |
| `force_pid_filter` | 0 | Force PID filtering on/off | | `force_pid_filter` | 0 | Force PID filtering on/off |
| `generic_bulk_ctrl_endpoint` | `0x01` | Control endpoint | | `generic_bulk_ctrl_endpoint` | `0x01` | Control endpoint |
Enable verbose logging with: Enable verbose logging with:
```bash ```bash
modprobe dvb_usb_gp8psk debug=0xff modprobe dvb_usb_gp8psk debug=0xff
``` ```
Or at runtime: Or at runtime:
```bash ```bash
echo 0xff > /sys/module/dvb_usb_gp8psk/parameters/debug echo 0xff > /sys/module/dvb_usb_gp8psk/parameters/debug
``` ```
## DVB Frontend Properties ## DVB Frontend Properties
The gp8psk frontend (`gp8psk-fe.c`) registers with the following capabilities: The gp8psk frontend (`gp8psk-fe.c`) registers with the following capabilities:
```c title="Frontend info structure" ```c title="Frontend info structure"
.name = "Genpix 8psk-to-USB2 DVB-S" .name = "Genpix 8psk-to-USB2 DVB-S"
.frequency_min_hz = 800 * MHz .frequency_min_hz = 800 * MHz
.frequency_max_hz = 2250 * MHz .frequency_max_hz = 2250 * MHz
.frequency_stepsize_hz = 100 * kHz .frequency_stepsize_hz = 100 * kHz
.symbol_rate_min = 256000 // 256 Ksps .symbol_rate_min = 256000 // 256 Ksps
.symbol_rate_max = 30000000 // 30 Msps .symbol_rate_max = 30000000 // 30 Msps
.caps = FE_CAN_INVERSION_AUTO | .caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 |
FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK FE_CAN_QPSK
``` ```
<Aside type="note"> <Aside type="note">
The frontend capabilities only advertise `FE_CAN_QPSK` -- the turbo 8PSK, turbo 16QAM, and DCII modes are not exposed through the standard DVB API. Accessing these modes requires direct vendor command access or the Windows BDA driver. The frontend capabilities only advertise `FE_CAN_QPSK` -- the turbo 8PSK, turbo 16QAM, and DCII modes are not exposed through the standard DVB API. Accessing these modes requires direct vendor command access or the Windows BDA driver.
</Aside> </Aside>
## Related Pages ## Related Pages
- [Vendor Commands](/usb/vendor-commands/) -- Complete command reference - [Vendor Commands](/usb/vendor-commands/) -- Complete command reference
- [Kernel FW01](/firmware/kernel-fw01/) -- Firmware format and loading analysis - [Kernel FW01](/firmware/kernel-fw01/) -- Firmware format and loading analysis
- [DVB-S2 Investigation](/driver/dvb-s2/) -- Why DVB-S2 cannot be added - [DVB-S2 Investigation](/driver/dvb-s2/) -- Why DVB-S2 cannot be added
- [Custom Firmware v3.01](/firmware/custom-v301/) -- Open-source replacement with extended commands - [Custom Firmware v3.01](/firmware/custom-v301/) -- Open-source replacement with extended commands

View File

@ -1,291 +1,291 @@
--- ---
title: Custom Firmware v3.01 title: Custom Firmware v3.01
description: Open-source SDCC + fx2lib replacement firmware with spectrum sweep, blind scan, raw demod access, and hardware diagnostics. description: Open-source SDCC + fx2lib replacement firmware with spectrum sweep, blind scan, raw demod access, and hardware diagnostics.
--- ---
import { Steps, Badge, Aside, Tabs, TabItem, FileTree } from '@astrojs/starlight/components'; import { Steps, Badge, Aside, Tabs, TabItem, FileTree } from '@astrojs/starlight/components';
The custom firmware is an open-source replacement for the stock SkyWalker-1 FX2 firmware, built with the SDCC compiler and fx2lib library. It implements all stock vendor commands for kernel driver compatibility and adds diagnostic, spectrum sweep, blind scan, and raw register access capabilities. <Badge text="Custom" variant="success" /> The custom firmware is an open-source replacement for the stock SkyWalker-1 FX2 firmware, built with the SDCC compiler and fx2lib library. It implements all stock vendor commands for kernel driver compatibility and adds diagnostic, spectrum sweep, blind scan, and raw register access capabilities. <Badge text="Custom" variant="success" />
See also: [v3.02](/firmware/custom-v302/) adds signal monitoring, tune-and-measure, and batch register read commands on top of this base. See also: [v3.02](/firmware/custom-v302/) adds signal monitoring, tune-and-measure, and batch register read commands on top of this base.
## Project Structure ## Project Structure
<FileTree> <FileTree>
- firmware/ - firmware/
- skywalker1.c Main firmware source (1351 lines) - skywalker1.c Main firmware source (1351 lines)
- Makefile SDCC build rules - Makefile SDCC build rules
- skywalker1.ihx Compiled Intel HEX output - skywalker1.ihx Compiled Intel HEX output
- tools/ - tools/
- fw_load.py FX2 RAM loader utility - fw_load.py FX2 RAM loader utility
- eeprom_flash.py EEPROM flash tool - eeprom_flash.py EEPROM flash tool
</FileTree> </FileTree>
## Architecture Overview ## Architecture Overview
| Property | Value | | Property | Value |
|----------|-------| |----------|-------|
| Toolchain | SDCC 4.x + fx2lib | | Toolchain | SDCC 4.x + fx2lib |
| Target | Cypress CY7C68013A (FX2LP) | | Target | Cypress CY7C68013A (FX2LP) |
| Load method | RAM upload via `fw_load.py` (USB 0xA0 vendor request) | | Load method | RAM upload via `fw_load.py` (USB 0xA0 vendor request) |
| Binary size | ~3 KB | | Binary size | ~3 KB |
| Source lines | 1351 | | Source lines | 1351 |
| DiSEqC data pin | P0.7 (matches v2.06 hardware) | | DiSEqC data pin | P0.7 (matches v2.06 hardware) |
| BCM4500 I2C address | `0x08` (7-bit); wire address `0x10`/`0x11` | | BCM4500 I2C address | `0x08` (7-bit); wire address `0x10`/`0x11` |
<Aside type="tip"> <Aside type="tip">
To build the firmware from source: To build the firmware from source:
```bash ```bash
cd firmware/ cd firmware/
make # Produces skywalker1.ihx make # Produces skywalker1.ihx
``` ```
To load into FX2 RAM (does not persist across power cycles): To load into FX2 RAM (does not persist across power cycles):
```bash ```bash
python tools/fw_load.py firmware/skywalker1.ihx python tools/fw_load.py firmware/skywalker1.ihx
``` ```
To make the firmware persistent, flash it to the onboard EEPROM using `eeprom_flash.py`. To make the firmware persistent, flash it to the onboard EEPROM using `eeprom_flash.py`.
</Aside> </Aside>
## Stock-Compatible Commands ## Stock-Compatible Commands
All stock vendor commands (`0x80`--`0x94`) are implemented for full compatibility with the Linux `dvb_usb_gp8psk` kernel driver: All stock vendor commands (`0x80`--`0x94`) are implemented for full compatibility with the Linux `dvb_usb_gp8psk` kernel driver:
| Command | Name | Implementation | | Command | Name | Implementation |
|---------|------|---------------| |---------|------|---------------|
| `0x80` | GET_8PSK_CONFIG | Returns `config_status` byte (1 byte) | | `0x80` | GET_8PSK_CONFIG | Returns `config_status` byte (1 byte) |
| `0x85` | ARM_TRANSFER | Calls `gpif_start()` / `gpif_stop()` | | `0x85` | ARM_TRANSFER | Calls `gpif_start()` / `gpif_stop()` |
| `0x86` | TUNE_8PSK | Parses 10-byte EP0 payload, programs BCM4500 | | `0x86` | TUNE_8PSK | Parses 10-byte EP0 payload, programs BCM4500 |
| `0x87` | GET_SIGNAL_STRENGTH | Reads 6 BCM4500 indirect registers | | `0x87` | GET_SIGNAL_STRENGTH | Reads 6 BCM4500 indirect registers |
| `0x89` | BOOT_8PSK | Full BCM4500 boot sequence (see below) | | `0x89` | BOOT_8PSK | Full BCM4500 boot sequence (see below) |
| `0x8A` | START_INTERSIL | Enables/disables LNB power supply | | `0x8A` | START_INTERSIL | Enables/disables LNB power supply |
| `0x8B` | SET_LNB_VOLTAGE | Sets P0.4 for 13V/18V selection | | `0x8B` | SET_LNB_VOLTAGE | Sets P0.4 for 13V/18V selection |
| `0x8C` | SET_22KHZ_TONE | Sets P0.3 for 22 kHz oscillator gate | | `0x8C` | SET_22KHZ_TONE | Sets P0.3 for 22 kHz oscillator gate |
| `0x8D` | SEND_DISEQC | DiSEqC tone burst via Timer2 bit-bang | | `0x8D` | SEND_DISEQC | DiSEqC tone burst via Timer2 bit-bang |
| `0x90` | GET_SIGNAL_LOCK | Reads BCM4500 lock register `0xA4` | | `0x90` | GET_SIGNAL_LOCK | Reads BCM4500 lock register `0xA4` |
| `0x92` | GET_FW_VERS | Returns version `0x030100`, build date | | `0x92` | GET_FW_VERS | Returns version `0x030100`, build date |
| `0x94` | USE_EXTRA_VOLT | Writes `0x62`/`0x6A` to XRAM `0xE0B6` | | `0x94` | USE_EXTRA_VOLT | Writes `0x62`/`0x6A` to XRAM `0xE0B6` |
## Custom Diagnostic Commands ## Custom Diagnostic Commands
Seven new vendor commands (`0xB0`--`0xB6`) extend the firmware with capabilities absent from all stock versions: <Badge text="New" variant="success" /> Seven new vendor commands (`0xB0`--`0xB6`) extend the firmware with capabilities absent from all stock versions: <Badge text="New" variant="success" />
| Command | Name | Direction | Payload | Purpose | | Command | Name | Direction | Payload | Purpose |
|---------|------|-----------|---------|---------| |---------|------|-----------|---------|---------|
| `0xB0` | SPECTRUM_SWEEP | OUT+Bulk | 10 bytes EP0 | Step through frequencies, return power readings via EP2 | | `0xB0` | SPECTRUM_SWEEP | OUT+Bulk | 10 bytes EP0 | Step through frequencies, return power readings via EP2 |
| `0xB1` | RAW_DEMOD_READ | IN | 2 bytes | Read arbitrary BCM4500 indirect register | | `0xB1` | RAW_DEMOD_READ | IN | 2 bytes | Read arbitrary BCM4500 indirect register |
| `0xB2` | RAW_DEMOD_WRITE | OUT | 3 bytes | Write arbitrary BCM4500 indirect register | | `0xB2` | RAW_DEMOD_WRITE | OUT | 3 bytes | Write arbitrary BCM4500 indirect register |
| `0xB3` | BLIND_SCAN | OUT+EP0 | 16 bytes EP0 | Sweep symbol rates at a frequency, report lock | | `0xB3` | BLIND_SCAN | OUT+EP0 | 16 bytes EP0 | Sweep symbol rates at a frequency, report lock |
| `0xB4` | I2C_SCAN | IN | N bytes | Scan I2C bus for responsive devices | | `0xB4` | I2C_SCAN | IN | N bytes | Scan I2C bus for responsive devices |
| `0xB5` | GET_BOOT_STAGE | IN | 2 bytes | Read `config_status` + `boot_stage` | | `0xB5` | GET_BOOT_STAGE | IN | 2 bytes | Read `config_status` + `boot_stage` |
| `0xB6` | GET_GPIO_STATE | IN | 3 bytes | Read IOA, IOB, IOD port registers | | `0xB6` | GET_GPIO_STATE | IN | 3 bytes | Read IOA, IOB, IOD port registers |
### Spectrum Sweep (0xB0) ### Spectrum Sweep (0xB0)
Steps through frequencies from start to stop, reading BCM4500 signal energy at each step. Results are packed as u16 LE values into EP2 bulk endpoint. Steps through frequencies from start to stop, reading BCM4500 signal energy at each step. Results are packed as u16 LE values into EP2 bulk endpoint.
```c title="Spectrum sweep EP0 payload (10 bytes)" ```c title="Spectrum sweep EP0 payload (10 bytes)"
EP0BUF[0..3] start_freq (u32 LE, kHz) EP0BUF[0..3] start_freq (u32 LE, kHz)
EP0BUF[4..7] stop_freq (u32 LE, kHz) EP0BUF[4..7] stop_freq (u32 LE, kHz)
EP0BUF[8..9] step_khz (u16 LE, default 1000 if 0) EP0BUF[8..9] step_khz (u16 LE, default 1000 if 0)
``` ```
At each step, the firmware programs the BCM4500 frequency register via indirect write, waits 10 ms for settling, reads the SNR register pair, and packs the result into EP2 FIFO. When the buffer reaches 512 bytes, it is committed to the host. At each step, the firmware programs the BCM4500 frequency register via indirect write, waits 10 ms for settling, reads the SNR register pair, and packs the result into EP2 FIFO. When the buffer reaches 512 bytes, it is committed to the host.
### Blind Scan (0xB3) ### Blind Scan (0xB3)
Sweeps symbol rates from `sr_min` to `sr_max` at a given frequency, checking for signal lock at each step. Sweeps symbol rates from `sr_min` to `sr_max` at a given frequency, checking for signal lock at each step.
```c title="Blind scan EP0 payload (16 bytes)" ```c title="Blind scan EP0 payload (16 bytes)"
EP0BUF[0..3] freq_khz (u32 LE) EP0BUF[0..3] freq_khz (u32 LE)
EP0BUF[4..7] sr_min (u32 LE, sps) EP0BUF[4..7] sr_min (u32 LE, sps)
EP0BUF[8..11] sr_max (u32 LE, sps) EP0BUF[8..11] sr_max (u32 LE, sps)
EP0BUF[12..15] sr_step (u32 LE, sps, default 1000000 if 0) EP0BUF[12..15] sr_step (u32 LE, sps, default 1000000 if 0)
``` ```
Returns 8 bytes on lock (`freq_khz[4] + sr_locked[4]`), or 1 byte `0x00` if no lock found. Returns 8 bytes on lock (`freq_khz[4] + sr_locked[4]`), or 1 byte `0x00` if no lock found.
### Raw Demod Access (0xB1 / 0xB2) ### Raw Demod Access (0xB1 / 0xB2)
Direct access to any BCM4500 indirect register, bypassing the stock firmware's limited register set: Direct access to any BCM4500 indirect register, bypassing the stock firmware's limited register set:
```c title="Raw demod read (0xB1)" ```c title="Raw demod read (0xB1)"
// wValue = register page, wIndex = register number // wValue = register page, wIndex = register number
// Returns 1 byte in EP0 // Returns 1 byte in EP0
bcm_indirect_read(page, &val); bcm_indirect_read(page, &val);
EP0BUF[0] = val; EP0BUF[0] = val;
``` ```
```c title="Raw demod write (0xB2)" ```c title="Raw demod write (0xB2)"
// wValue = register page, wIndex = register number // wValue = register page, wIndex = register number
// EP0 data = 1 byte value // EP0 data = 1 byte value
bcm_indirect_write(page, val); bcm_indirect_write(page, val);
``` ```
## BCM4500 Boot Sequence ## BCM4500 Boot Sequence
The `bcm4500_boot()` function replicates the stock firmware's initialization with added diagnostic instrumentation. The `boot_stage` variable tracks progress for debugging failed boots. The `bcm4500_boot()` function replicates the stock firmware's initialization with added diagnostic instrumentation. The `boot_stage` variable tracks progress for debugging failed boots.
<Steps> <Steps>
1. **GPIO setup** (`boot_stage = 1`): Set P3.7/P3.6/P3.5 HIGH (control lines idle), assert BCM4500 RESET (P0.5 LOW) 1. **GPIO setup** (`boot_stage = 1`): Set P3.7/P3.6/P3.5 HIGH (control lines idle), assert BCM4500 RESET (P0.5 LOW)
2. **Power on** (`boot_stage = 2`): Enable power supply (P0.1 HIGH, P0.2 LOW), wait 30 ms for settling, release RESET (P0.5 HIGH), wait 50 ms for BCM4500 POR 2. **Power on** (`boot_stage = 2`): Enable power supply (P0.1 HIGH, P0.2 LOW), wait 30 ms for settling, release RESET (P0.5 HIGH), wait 50 ms for BCM4500 POR
3. **I2C probe** (`boot_stage = 3`): Read BCM4500 status register `0xA2` to verify the chip is alive on the I2C bus 3. **I2C probe** (`boot_stage = 3`): Read BCM4500 status register `0xA2` to verify the chip is alive on the I2C bus
4. **Init block 0** (`boot_stage = 4`): Write 7-byte configuration block to BCM4500 page 0 indirect registers 4. **Init block 0** (`boot_stage = 4`): Write 7-byte configuration block to BCM4500 page 0 indirect registers
5. **Init block 1** (`boot_stage = 5`): Write 8-byte configuration block 5. **Init block 1** (`boot_stage = 5`): Write 8-byte configuration block
6. **Init block 2** (`boot_stage = 6`): Write 3-byte configuration block 6. **Init block 2** (`boot_stage = 6`): Write 3-byte configuration block
7. **Success** (`boot_stage = 0xFF`): Set `BM_STARTED | BM_FW_LOADED` in config status 7. **Success** (`boot_stage = 0xFF`): Set `BM_STARTED | BM_FW_LOADED` in config status
</Steps> </Steps>
### BCM4500 Init Data ### BCM4500 Init Data
Three initialization blocks extracted from stock v2.06 firmware (`FUN_CODE_0ddd`): Three initialization blocks extracted from stock v2.06 firmware (`FUN_CODE_0ddd`):
```c title="BCM4500 register initialization data" ```c title="BCM4500 register initialization data"
static const __code BYTE bcm_init_block0[] = { static const __code BYTE bcm_init_block0[] = {
0x06, 0x0b, 0x17, 0x38, 0x9f, 0xd9, 0x80 0x06, 0x0b, 0x17, 0x38, 0x9f, 0xd9, 0x80
}; };
static const __code BYTE bcm_init_block1[] = { static const __code BYTE bcm_init_block1[] = {
0x07, 0x09, 0x39, 0x4f, 0x00, 0x65, 0xb7, 0x10 0x07, 0x09, 0x39, 0x4f, 0x00, 0x65, 0xb7, 0x10
}; };
static const __code BYTE bcm_init_block2[] = { static const __code BYTE bcm_init_block2[] = {
0x0f, 0x0c, 0x09 0x0f, 0x0c, 0x09
}; };
``` ```
Each block is written to BCM4500 page 0 via the indirect register protocol: page select to `0xA6`, data bytes to `0xA7`, trailing zero to `0xA7`, commit `0x03` to `0xA8`, then poll for completion. Each block is written to BCM4500 page 0 via the indirect register protocol: page select to `0xA6`, data bytes to `0xA7`, trailing zero to `0xA7`, commit `0x03` to `0xA8`, then poll for completion.
### Debug Boot Modes ### Debug Boot Modes
The BOOT_8PSK command (`0x89`) accepts debug wValue parameters that execute partial boot sequences for incremental hardware debugging: The BOOT_8PSK command (`0x89`) accepts debug wValue parameters that execute partial boot sequences for incremental hardware debugging:
| wValue | Stage | What It Does | Success Marker | | wValue | Stage | What It Does | Success Marker |
|--------|-------|-------------|----------------| |--------|-------|-------------|----------------|
| `0x80` | None | No-op, return current state | -- | | `0x80` | None | No-op, return current state | -- |
| `0x81` | GPIO only | GPIO setup + power + reset, no I2C | `0xA1` | | `0x81` | GPIO only | GPIO setup + power + reset, no I2C | `0xA1` |
| `0x82` | GPIO + probe | GPIO + I2C read of status register | `0xA2` | | `0x82` | GPIO + probe | GPIO + I2C read of status register | `0xA2` |
| `0x83` | GPIO + probe + block 0 | GPIO + I2C + first init block | `0xA3` | | `0x83` | GPIO + probe + block 0 | GPIO + I2C + first init block | `0xA3` |
| `0x84` | I2C only | Probe without GPIO (chip must be powered) | `0xA4` | | `0x84` | I2C only | Probe without GPIO (chip must be powered) | `0xA4` |
| `0x85` | GPIO + probe (no bus reset) | Same as `0x82` without I2CS bmSTOP | `0xA5` | | `0x85` | GPIO + probe (no bus reset) | Same as `0x82` without I2CS bmSTOP | `0xA5` |
| `0x01` | Full boot | Complete `bcm4500_boot()` sequence | `0xFF` | | `0x01` | Full boot | Complete `bcm4500_boot()` sequence | `0xFF` |
| `0x00` | Shutdown | Power off BCM4500 | -- | | `0x00` | Shutdown | Power off BCM4500 | -- |
<Aside type="note"> <Aside type="note">
Debug mode `0x85` was created to isolate a critical bug: sending an I2C STOP when no transaction is active corrupts the FX2 I2C controller state, causing subsequent START+ACK detection to fail. The spurious STOP was present in early custom firmware revisions and was the root cause of BCM4500 boot failures. Removing it fixed the issue. Debug mode `0x85` was created to isolate a critical bug: sending an I2C STOP when no transaction is active corrupts the FX2 I2C controller state, causing subsequent START+ACK detection to fail. The spurious STOP was present in early custom firmware revisions and was the root cause of BCM4500 boot failures. Removing it fixed the issue.
</Aside> </Aside>
## I2C Implementation ## I2C Implementation
The custom firmware implements I2C from scratch rather than using fx2lib's I2C functions, providing full timeout protection: The custom firmware implements I2C from scratch rather than using fx2lib's I2C functions, providing full timeout protection:
```c title="I2C timeout constant" ```c title="I2C timeout constant"
#define I2C_TIMEOUT 6000 // ~5ms at 48MHz (4 clocks/cycle, ~12 MIPS) #define I2C_TIMEOUT 6000 // ~5ms at 48MHz (4 clocks/cycle, ~12 MIPS)
``` ```
Key I2C functions: Key I2C functions:
| Function | Purpose | | Function | Purpose |
|----------|---------| |----------|---------|
| `i2c_wait_done()` | Poll `I2CS.bmDONE` with 6000-count timeout | | `i2c_wait_done()` | Poll `I2CS.bmDONE` with 6000-count timeout |
| `i2c_wait_stop()` | Poll `I2CS.bmSTOP` clear with timeout | | `i2c_wait_stop()` | Poll `I2CS.bmSTOP` clear with timeout |
| `i2c_combined_read()` | Write-then-read with repeated START (no intermediate STOP) | | `i2c_combined_read()` | Write-then-read with repeated START (no intermediate STOP) |
| `i2c_write_timeout()` | Single-byte write with timeout on each phase | | `i2c_write_timeout()` | Single-byte write with timeout on each phase |
| `i2c_write_multi_timeout()` | Multi-byte write with timeout | | `i2c_write_multi_timeout()` | Multi-byte write with timeout |
<Aside type="caution"> <Aside type="caution">
Stock firmware has no I2C timeout -- if the BCM4500 holds SCL low (clock stretching), the FX2 spins forever. The custom firmware's 6000-count timeout provides ~5 ms margin at 48 MHz, which is more than 200x the time needed for a single I2C byte at 400 kHz. Stock firmware has no I2C timeout -- if the BCM4500 holds SCL low (clock stretching), the FX2 spins forever. The custom firmware's 6000-count timeout provides ~5 ms margin at 48 MHz, which is more than 200x the time needed for a single I2C byte at 400 kHz.
</Aside> </Aside>
### BCM4500 Register Access ### BCM4500 Register Access
The BCM4500 uses an indirect register protocol through three I2C registers: The BCM4500 uses an indirect register protocol through three I2C registers:
| Register | Address | Purpose | | Register | Address | Purpose |
|----------|---------|---------| |----------|---------|---------|
| BCM_REG_PAGE | `0xA6` | Page/register select | | BCM_REG_PAGE | `0xA6` | Page/register select |
| BCM_REG_DATA | `0xA7` | Data read/write | | BCM_REG_DATA | `0xA7` | Data read/write |
| BCM_REG_CMD | `0xA8` | Command trigger (`0x01` = read, `0x03` = write) | | BCM_REG_CMD | `0xA8` | Command trigger (`0x01` = read, `0x03` = write) |
```c title="Indirect register read sequence" ```c title="Indirect register read sequence"
// 1. Write [page, 0x00, 0x01] to A6/A7/A8 in one I2C transaction // 1. Write [page, 0x00, 0x01] to A6/A7/A8 in one I2C transaction
// 2. Wait for command completion (poll A8 bit 0 == 0) // 2. Wait for command completion (poll A8 bit 0 == 0)
// 3. Read result from A7 // 3. Read result from A7
``` ```
## GPIF Streaming ## GPIF Streaming
Transport stream data from the BCM4500 flows through the FX2's GPIF engine into USB endpoint EP2: Transport stream data from the BCM4500 flows through the FX2's GPIF engine into USB endpoint EP2:
```c title="GPIF configuration" ```c title="GPIF configuration"
IFCONFIG = 0xEE; // Internal 48MHz, GPIF master, async, clock output IFCONFIG = 0xEE; // Internal 48MHz, GPIF master, async, clock output
EP2FIFOCFG = 0x0C; // AUTOIN, ZEROLENIN, 8-bit EP2FIFOCFG = 0x0C; // AUTOIN, ZEROLENIN, 8-bit
FLOWSTATE |= 0x09; // Enable flow state + FS[3] FLOWSTATE |= 0x09; // Enable flow state + FS[3]
GPIFTCB3 = 0x80; // Transaction count = 0x80000000 (effectively infinite) GPIFTCB3 = 0x80; // Transaction count = 0x80000000 (effectively infinite)
``` ```
The `gpif_start()` function arms the GPIF for continuous read into EP2, while `gpif_stop()` flushes the FIFO and de-asserts the BCM4500 control lines on P3. The `gpif_start()` function arms the GPIF for continuous read into EP2, while `gpif_stop()` flushes the FIFO and de-asserts the BCM4500 control lines on P3.
## GPIO Pin Map ## GPIO Pin Map
```c title="GPIO pin definitions (v2.06 hardware)" ```c title="GPIO pin definitions (v2.06 hardware)"
#define PIN_PWR_EN 0x02 // P0.1 -- power supply enable #define PIN_PWR_EN 0x02 // P0.1 -- power supply enable
#define PIN_PWR_DIS 0x04 // P0.2 -- power supply disable #define PIN_PWR_DIS 0x04 // P0.2 -- power supply disable
#define PIN_22KHZ 0x08 // P0.3 -- 22kHz oscillator gate #define PIN_22KHZ 0x08 // P0.3 -- 22kHz oscillator gate
#define PIN_LNB_VOLT 0x10 // P0.4 -- LNB voltage select #define PIN_LNB_VOLT 0x10 // P0.4 -- LNB voltage select
#define PIN_BCM_RESET 0x20 // P0.5 -- BCM4500 hardware reset #define PIN_BCM_RESET 0x20 // P0.5 -- BCM4500 hardware reset
#define PIN_DISEQC 0x80 // P0.7 -- DiSEqC data #define PIN_DISEQC 0x80 // P0.7 -- DiSEqC data
``` ```
Initial state after `TD_Init()`: Initial state after `TD_Init()`:
- `IOA = 0x84` (P0.7 HIGH, P0.2 HIGH -- power disabled, streaming off) - `IOA = 0x84` (P0.7 HIGH, P0.2 HIGH -- power disabled, streaming off)
- `OEA = 0xBE` (P0.1 through P0.5 and P0.7 as outputs) - `OEA = 0xBE` (P0.1 through P0.5 and P0.7 as outputs)
## Differences from Stock Firmware ## Differences from Stock Firmware
| Feature | Stock v2.06 | Custom v3.01 | | Feature | Stock v2.06 | Custom v3.01 |
|---------|-------------|--------------| |---------|-------------|--------------|
| Toolchain | Unknown (proprietary) | SDCC + fx2lib (open source) | | Toolchain | Unknown (proprietary) | SDCC + fx2lib (open source) |
| I2C timeout | None (infinite spin) | 6000-count (~5 ms) | | I2C timeout | None (infinite spin) | 6000-count (~5 ms) |
| Boot diagnostics | None | Incremental debug modes | | Boot diagnostics | None | Incremental debug modes |
| Custom commands | None | 7 (`0xB0`--`0xB6`) | | Custom commands | None | 7 (`0xB0`--`0xB6`) |
| Spectrum sweep | Not possible | `0xB0` via EP2 bulk | | Spectrum sweep | Not possible | `0xB0` via EP2 bulk |
| Blind scan | Not possible | `0xB3` with SR sweep | | Blind scan | Not possible | `0xB3` with SR sweep |
| Raw register access | Not possible | `0xB1`/`0xB2` | | Raw register access | Not possible | `0xB1`/`0xB2` |
| I2C bus scan | Not possible | `0xB4` | | I2C bus scan | Not possible | `0xB4` |
| GPIO read | Not possible | `0xB6` | | GPIO read | Not possible | `0xB6` |
| Anti-tampering | Present (v2.13) | Removed | | Anti-tampering | Present (v2.13) | Removed |
| Source available | No | Yes (`firmware/skywalker1.c`) | | Source available | No | Yes (`firmware/skywalker1.c`) |
See the [v3.02 comparison table](/firmware/custom-v302/#what-changed-from-v301) for signal monitoring and batch register improvements added on top of v3.01. See the [v3.02 comparison table](/firmware/custom-v302/#what-changed-from-v301) for signal monitoring and batch register improvements added on top of v3.01.
## Tuning Implementation ## Tuning Implementation
The `do_tune()` function parses the same 10-byte EP0 payload as the stock firmware: The `do_tune()` function parses the same 10-byte EP0 payload as the stock firmware:
```c title="Tune command payload parsing" ```c title="Tune command payload parsing"
// Byte-reverse symbol rate and frequency from LE to BE // Byte-reverse symbol rate and frequency from LE to BE
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
tune_data[i] = EP0BUF[3 - i]; // Symbol rate (BE) tune_data[i] = EP0BUF[3 - i]; // Symbol rate (BE)
tune_data[4 + i] = EP0BUF[7 - i]; // Frequency (BE) tune_data[4 + i] = EP0BUF[7 - i]; // Frequency (BE)
} }
tune_data[8] = EP0BUF[8]; // Modulation type (0-9) tune_data[8] = EP0BUF[8]; // Modulation type (0-9)
tune_data[9] = EP0BUF[9]; // FEC index tune_data[9] = EP0BUF[9]; // FEC index
tune_data[10] = 0x10; // Demod mode (standard) tune_data[10] = 0x10; // Demod mode (standard)
tune_data[11] = 0x00; // Turbo flag tune_data[11] = 0x00; // Turbo flag
``` ```
Modulation-specific handling: Modulation-specific handling:
- Modulation types 1--3 (turbo modes): Set turbo flag `tune_data[11] = 0x01` - Modulation types 1--3 (turbo modes): Set turbo flag `tune_data[11] = 0x01`
- Modulation type 5: DCII I-stream, demod mode `0x12` - Modulation type 5: DCII I-stream, demod mode `0x12`
- Modulation type 6: DCII Q-stream, demod mode `0x16` - Modulation type 6: DCII Q-stream, demod mode `0x16`
- Modulation type 7: DCII offset QPSK, demod mode `0x11` - Modulation type 7: DCII offset QPSK, demod mode `0x11`

View File

@ -1,80 +1,80 @@
--- ---
title: Custom Firmware v3.02 title: Custom Firmware v3.02
description: Signal monitoring, tune-and-measure, and batch register read commands for real-time RF analysis. description: Signal monitoring, tune-and-measure, and batch register read commands for real-time RF analysis.
--- ---
import { Badge, Aside } from '@astrojs/starlight/components'; import { Badge, Aside } from '@astrojs/starlight/components';
Firmware v3.02 adds three new vendor commands (`0xB7`--`0xB9`) optimized for real-time signal monitoring and RF analysis workflows. These commands reduce USB round-trips by combining multiple register reads into single transfers. <Badge text="v3.02" variant="success" /> Firmware v3.02 adds three new vendor commands (`0xB7`--`0xB9`) optimized for real-time signal monitoring and RF analysis workflows. These commands reduce USB round-trips by combining multiple register reads into single transfers. <Badge text="v3.02" variant="success" />
Built on the same [v3.01 codebase](/firmware/custom-v301/) — same SDCC + fx2lib toolchain, same stock-compatible command set, same I2C timeout protection. Built on the same [v3.01 codebase](/firmware/custom-v301/) — same SDCC + fx2lib toolchain, same stock-compatible command set, same I2C timeout protection.
| Property | Value | | Property | Value |
|----------|-------| |----------|-------|
| Version ID | `0x030200` | | Version ID | `0x030200` |
| Date | 2026-02-12 | | Date | 2026-02-12 |
| New commands | `0xB7`--`0xB9` (3 added to v3.01's 7) | | New commands | `0xB7`--`0xB9` (3 added to v3.01's 7) |
| Total custom commands | 10 (`0xB0`--`0xB9`) | | Total custom commands | 10 (`0xB0`--`0xB9`) |
## New Commands ## New Commands
| Command | Name | Direction | Payload | Purpose | | Command | Name | Direction | Payload | Purpose |
|---------|------|-----------|---------|---------| |---------|------|-----------|---------|---------|
| `0xB7` | SIGNAL_MONITOR | IN | 8 bytes | Fast combined read: SNR + AGC + lock + status | | `0xB7` | SIGNAL_MONITOR | IN | 8 bytes | Fast combined read: SNR + AGC + lock + status |
| `0xB8` | TUNE_MONITOR | OUT+IN | 10 bytes each | Tune + dwell + read in one round-trip | | `0xB8` | TUNE_MONITOR | OUT+IN | 10 bytes each | Tune + dwell + read in one round-trip |
| `0xB9` | MULTI_REG_READ | IN | 1--64 bytes | Batch read contiguous indirect registers | | `0xB9` | MULTI_REG_READ | IN | 1--64 bytes | Batch read contiguous indirect registers |
## Signal Monitor (0xB7) ## Signal Monitor (0xB7)
Combines six indirect register reads and two direct register reads into a single 8-byte USB transfer. Replaces three separate transfers (`GET_SIGNAL_STRENGTH` + `GET_SIGNAL_LOCK` + individual register reads) with one. Combines six indirect register reads and two direct register reads into a single 8-byte USB transfer. Replaces three separate transfers (`GET_SIGNAL_STRENGTH` + `GET_SIGNAL_LOCK` + individual register reads) with one.
```c title="SIGNAL_MONITOR response format (8 bytes)" ```c title="SIGNAL_MONITOR response format (8 bytes)"
Bytes 0-1: SNR (u16 LE, indirect regs 0x00-0x01, dBu × 256) Bytes 0-1: SNR (u16 LE, indirect regs 0x00-0x01, dBu × 256)
Bytes 2-3: AGC1 (u16 LE, indirect regs 0x02-0x03) Bytes 2-3: AGC1 (u16 LE, indirect regs 0x02-0x03)
Bytes 4-5: AGC2 (u16 LE, indirect regs 0x04-0x05) Bytes 4-5: AGC2 (u16 LE, indirect regs 0x04-0x05)
Byte 6: Lock (direct reg 0xA4, bit 5 = locked) Byte 6: Lock (direct reg 0xA4, bit 5 = locked)
Byte 7: Status (direct reg 0xA2) Byte 7: Status (direct reg 0xA2)
``` ```
Enables ~50 Hz polling for real-time dish alignment feedback. Enables ~50 Hz polling for real-time dish alignment feedback.
## Tune Monitor (0xB8) ## Tune Monitor (0xB8)
Combines tune + configurable dwell + signal read into one command round-trip. This is the building block for host-driven spectrum sweeps. Combines tune + configurable dwell + signal read into one command round-trip. This is the building block for host-driven spectrum sweeps.
The command uses two USB control transfers sharing the same bRequest code, distinguished by direction: The command uses two USB control transfers sharing the same bRequest code, distinguished by direction:
```c title="TUNE_MONITOR protocol" ```c title="TUNE_MONITOR protocol"
// Phase 1: OUT (0x40) — host sends 10-byte tune payload // Phase 1: OUT (0x40) — host sends 10-byte tune payload
// wValue = dwell_ms (1-255), firmware tunes, waits, reads signal // wValue = dwell_ms (1-255), firmware tunes, waits, reads signal
// Phase 2: IN (0xC0) — host reads 10-byte result // Phase 2: IN (0xC0) — host reads 10-byte result
// Bytes 0-5: SNR(2) + AGC1(2) + AGC2(2) // Bytes 0-5: SNR(2) + AGC1(2) + AGC2(2)
// Byte 6: lock, Byte 7: status // Byte 6: lock, Byte 7: status
// Bytes 8-9: dwell_ms echo (u16 LE) // Bytes 8-9: dwell_ms echo (u16 LE)
``` ```
<Aside type="note"> <Aside type="note">
The OUT phase blocks for the full dwell time inside the FX2 vendor command handler. The USB STATUS phase does not complete until `handle_vendorcommand()` returns. With a maximum dwell of 255 ms and a USB timeout of 2000 ms, this is well within safe bounds. The OUT phase blocks for the full dwell time inside the FX2 vendor command handler. The USB STATUS phase does not complete until `handle_vendorcommand()` returns. With a maximum dwell of 255 ms and a USB timeout of 2000 ms, this is well within safe bounds.
</Aside> </Aside>
## Multi Register Read (0xB9) ## Multi Register Read (0xB9)
Batch-reads up to 64 contiguous BCM4500 indirect registers in a single USB transfer. Each register still requires an individual I2C read sequence internally, but eliminating 63 USB control transfer round-trips provides ~64x speedup for register exploration. Batch-reads up to 64 contiguous BCM4500 indirect registers in a single USB transfer. Each register still requires an individual I2C read sequence internally, but eliminating 63 USB control transfer round-trips provides ~64x speedup for register exploration.
```c title="MULTI_REG_READ parameters" ```c title="MULTI_REG_READ parameters"
wValue = start register number wValue = start register number
wIndex = count (1-64) wIndex = count (1-64)
Returns: count bytes, one per register Returns: count bytes, one per register
``` ```
## What Changed from v3.01 ## What Changed from v3.01
| Feature | v3.01 | v3.02 | | Feature | v3.01 | v3.02 |
|---------|-------|-------| |---------|-------|-------|
| Custom commands | 7 (`0xB0`--`0xB6`) | 10 (`0xB0`--`0xB9`) | | Custom commands | 7 (`0xB0`--`0xB6`) | 10 (`0xB0`--`0xB9`) |
| Spectrum sweep | `0xB0` via EP2 bulk (firmware-driven) | Also `0xB8` via control EP (host-driven) | | Spectrum sweep | `0xB0` via EP2 bulk (firmware-driven) | Also `0xB8` via control EP (host-driven) |
| Signal monitoring | 3 USB transfers (stock method) | 1 transfer (`0xB7`, 8 bytes) | | Signal monitoring | 3 USB transfers (stock method) | 1 transfer (`0xB7`, 8 bytes) |
| Batch register read | 1 reg per transfer | 64 regs per transfer (`0xB9`) | | Batch register read | 1 reg per transfer | 64 regs per transfer (`0xB9`) |
| All other features | -- | Unchanged | | All other features | -- | Unchanged |
The v3.01 commands (`0xB0`--`0xB6`) remain fully functional. See the [v3.01 documentation](/firmware/custom-v301/) for spectrum sweep, blind scan, raw demod access, I2C scan, boot stage, and GPIO state commands. The v3.01 commands (`0xB0`--`0xB6`) remain fully functional. See the [v3.01 documentation](/firmware/custom-v301/) for spectrum sweep, blind scan, raw demod access, I2C scan, boot stage, and GPIO state commands.

View File

@ -1,181 +1,181 @@
--- ---
title: Custom Firmware v3.05 title: Custom Firmware v3.05
description: Safety-hardened firmware with software watchdog, timeout protection on all I2C/USB/GPIF paths, and comprehensive error reporting. description: Safety-hardened firmware with software watchdog, timeout protection on all I2C/USB/GPIF paths, and comprehensive error reporting.
--- ---
import { Badge, Aside, Steps } from '@astrojs/starlight/components'; import { Badge, Aside, Steps } from '@astrojs/starlight/components';
Firmware v3.05.0 is the result of a systematic safety review applied to the entire codebase. Every infinite-spin loop has been replaced with timeout-protected equivalents, a software watchdog cuts LNB power if the main loop stalls, and every failure mode now sets a specific error code readable by the host. <Badge text="v3.05" variant="success" /> <Badge text="Safety" variant="caution" /> Firmware v3.05.0 is the result of a systematic safety review applied to the entire codebase. Every infinite-spin loop has been replaced with timeout-protected equivalents, a software watchdog cuts LNB power if the main loop stalls, and every failure mode now sets a specific error code readable by the host. <Badge text="v3.05" variant="success" /> <Badge text="Safety" variant="caution" />
Built on the [v3.04 codebase](/firmware/custom-v301/) — same SDCC + fx2lib toolchain, same stock-compatible command set, plus all custom commands from [v3.02](/firmware/custom-v302/) through v3.04. Built on the [v3.04 codebase](/firmware/custom-v301/) — same SDCC + fx2lib toolchain, same stock-compatible command set, plus all custom commands from [v3.02](/firmware/custom-v302/) through v3.04.
| Property | Value | | Property | Value |
|----------|-------| |----------|-------|
| Version ID | `0x030500` | | Version ID | `0x030500` |
| Date | 2026-02-16 | | Date | 2026-02-16 |
| Code size | 13,079 / 15,360 bytes (85%) | | Code size | 13,079 / 15,360 bytes (85%) |
| XRAM | 218 / 512 bytes (43%) | | XRAM | 218 / 512 bytes (43%) |
| Stack | 132 bytes available | | Stack | 132 bytes available |
| Source lines | 2,256 | | Source lines | 2,256 |
| New commands | None (safety hardening of existing paths) | | New commands | None (safety hardening of existing paths) |
## Motivation ## Motivation
The SkyWalker-1 controls an LNB power supply capable of 750 mA at 18V with no hardware watchdog on the FX2LP. A firmware hang leaves the power supply energized indefinitely. Prior firmware versions contained multiple paths where a stuck I2C bus, an unresponsive GPIF, or a slow EP0 transfer could spin forever without recovery. The SkyWalker-1 controls an LNB power supply capable of 750 mA at 18V with no hardware watchdog on the FX2LP. A firmware hang leaves the power supply energized indefinitely. Prior firmware versions contained multiple paths where a stuck I2C bus, an unresponsive GPIF, or a slow EP0 transfer could spin forever without recovery.
A structured safety review identified 21 issues across 4 severity levels: A structured safety review identified 21 issues across 4 severity levels:
| Severity | Count | Description | | Severity | Count | Description |
|----------|-------|-------------| |----------|-------|-------------|
| Critical | 3 | Infinite hangs in I2C bus scan, `do_tune()`, and DiSEqC Timer2 waits | | Critical | 3 | Infinite hangs in I2C bus scan, `do_tune()`, and DiSEqC Timer2 waits |
| High | 6 | Unprotected GPIF/EP0/EP2 waits, unchecked I2C returns in sweep functions | | High | 6 | Unprotected GPIF/EP0/EP2 waits, unchecked I2C returns in sweep functions |
| Medium | 7 | Missing error codes, payload validation, lock-bit magic numbers | | Medium | 7 | Missing error codes, payload validation, lock-bit magic numbers |
| Low | 5 | Code clarity, documentation, saturation guards | | Low | 5 | Code clarity, documentation, saturation guards |
## Software Watchdog ## Software Watchdog
A Timer0-based software watchdog provides a safety backstop for any remaining or unknown hang paths. A Timer0-based software watchdog provides a safety backstop for any remaining or unknown hang paths.
**Architecture:** **Architecture:**
- Timer0 runs in Mode 1 (16-bit, no auto-reload) at 4 MHz (48 MHz / 12) - Timer0 runs in Mode 1 (16-bit, no auto-reload) at 4 MHz (48 MHz / 12)
- Overflow period: 16.384 ms per tick - Overflow period: 16.384 ms per tick
- Watchdog window: 122 ticks = ~2 seconds - Watchdog window: 122 ticks = ~2 seconds
- The main loop calls `wdt_kick()` on every iteration to reset the counter - The main loop calls `wdt_kick()` on every iteration to reset the counter
- Long-running operations (spectrum sweep, blind scan) call `wdt_kick()` inside their loops - Long-running operations (spectrum sweep, blind scan) call `wdt_kick()` inside their loops
**If the watchdog fires:** **If the watchdog fires:**
<Steps> <Steps>
1. Timer0 ISR sets `IOA` to cut LNB power (`PIN_PWR_EN` off, `PIN_PWR_DIS` on) 1. Timer0 ISR sets `IOA` to cut LNB power (`PIN_PWR_EN` off, `PIN_PWR_DIS` on)
2. ISR sets `wdt_armed = 2` (fired state) — prevents re-arming 2. ISR sets `wdt_armed = 2` (fired state) — prevents re-arming
3. Main loop detects `wdt_armed == 2` on next iteration (if it recovers) 3. Main loop detects `wdt_armed == 2` on next iteration (if it recovers)
4. Main loop sets `last_error = ERR_WDT_FIRED` (0x0D) and clears `config_status` 4. Main loop sets `last_error = ERR_WDT_FIRED` (0x0D) and clears `config_status`
5. Host can read `ERR_WDT_FIRED` via `GET_LAST_ERROR` (0xBC) 5. Host can read `ERR_WDT_FIRED` via `GET_LAST_ERROR` (0xBC)
</Steps> </Steps>
<Aside type="caution"> <Aside type="caution">
The watchdog shares `IOA` with the main loop via read-modify-write. To avoid RMW races between the ISR and main-loop GPIO operations, `wdt_armed` uses a tri-state protocol: `0` = off, `1` = armed, `2` = fired. The ISR only writes `IOA` once (on fire), and `wdt_kick()` refuses to re-arm when `wdt_armed == 2`. The watchdog shares `IOA` with the main loop via read-modify-write. To avoid RMW races between the ISR and main-loop GPIO operations, `wdt_armed` uses a tri-state protocol: `0` = off, `1` = armed, `2` = fired. The ISR only writes `IOA` once (on fire), and `wdt_kick()` refuses to re-arm when `wdt_armed == 2`.
</Aside> </Aside>
## Timeout Protection ## Timeout Protection
Every bare spin loop in the firmware has been replaced with a countdown-protected equivalent. These are the paths that could previously hang forever: Every bare spin loop in the firmware has been replaced with a countdown-protected equivalent. These are the paths that could previously hang forever:
| Path | Location | Timeout | Error Code | | Path | Location | Timeout | Error Code |
|------|----------|---------|------------| |------|----------|---------|------------|
| `i2c_wait_done()` | I2C DONE bit | 6,000 iterations | `ERR_I2C_TIMEOUT` | | `i2c_wait_done()` | I2C DONE bit | 6,000 iterations | `ERR_I2C_TIMEOUT` |
| `i2c_wait_stop()` | I2C STOP bit | 6,000 iterations | `ERR_I2C_TIMEOUT` | | `i2c_wait_stop()` | I2C STOP bit | 6,000 iterations | `ERR_I2C_TIMEOUT` |
| `ep0_wait_data()` | EP0 BUSY bit | 6,000 iterations | `ERR_EP0_TIMEOUT` | | `ep0_wait_data()` | EP0 BUSY bit | 6,000 iterations | `ERR_EP0_TIMEOUT` |
| `gpif_start()` | GPIF idle | 60,000 iterations | `ERR_GPIF_TIMEOUT` | | `gpif_start()` | GPIF idle | 60,000 iterations | `ERR_GPIF_TIMEOUT` |
| `gpif_stop()` | GPIF idle | 60,000 iterations | `ERR_GPIF_TIMEOUT` | | `gpif_stop()` | GPIF idle | 60,000 iterations | `ERR_GPIF_TIMEOUT` |
| EP2 FIFO full | `do_param_sweep()` | 60,000 iterations | `ERR_EP2_TIMEOUT` | | EP2 FIFO full | `do_param_sweep()` | 60,000 iterations | `ERR_EP2_TIMEOUT` |
| EP2 FIFO full | `do_spectrum_sweep()` | 60,000 iterations | `ERR_EP2_TIMEOUT` | | EP2 FIFO full | `do_spectrum_sweep()` | 60,000 iterations | `ERR_EP2_TIMEOUT` |
| Timer2 overflow | `diseqc_wait_ticks()` | 6,000 per tick | `ERR_DISEQC_TIMER` | | Timer2 overflow | `diseqc_wait_ticks()` | 6,000 per tick | `ERR_DISEQC_TIMER` |
| I2C bus scan | `0xB4` handler | via `i2c_wait_done/stop` | `ERR_I2C_TIMEOUT` | | I2C bus scan | `0xB4` handler | via `i2c_wait_done/stop` | `ERR_I2C_TIMEOUT` |
The `ep0_wait_data()` helper replaces 7 separate bare `while (EP0CS & bmEPBUSY)` loops in vendor command handlers. After the wait, each handler validates `EP0BCL` against the expected payload size. The `ep0_wait_data()` helper replaces 7 separate bare `while (EP0CS & bmEPBUSY)` loops in vendor command handlers. After the wait, each handler validates `EP0BCL` against the expected payload size.
## Error Codes ## Error Codes
All error codes are set in the `last_error` variable and readable via `GET_LAST_ERROR` (0xBC). The error is sticky — it persists until overwritten by a new error. All error codes are set in the `last_error` variable and readable via `GET_LAST_ERROR` (0xBC). The error is sticky — it persists until overwritten by a new error.
| Code | Name | Meaning | | Code | Name | Meaning |
|------|------|---------| |------|------|---------|
| `0x00` | `ERR_OK` | No error | | `0x00` | `ERR_OK` | No error |
| `0x01` | `ERR_I2C_TIMEOUT` | I2C DONE or STOP bit timeout | | `0x01` | `ERR_I2C_TIMEOUT` | I2C DONE or STOP bit timeout |
| `0x02` | `ERR_I2C_NAK` | I2C slave did not ACK | | `0x02` | `ERR_I2C_NAK` | I2C slave did not ACK |
| `0x03` | `ERR_BCM_TIMEOUT` | BCM4500 poll-ready timeout | | `0x03` | `ERR_BCM_TIMEOUT` | BCM4500 poll-ready timeout |
| `0x04` | `ERR_BCM_NOT_READY` | BCM4500 not booted (tune attempted before boot) | | `0x04` | `ERR_BCM_NOT_READY` | BCM4500 not booted (tune attempted before boot) |
| `0x05` | `ERR_BCM_VERIFY` | BCM4500 register verify mismatch | | `0x05` | `ERR_BCM_VERIFY` | BCM4500 register verify mismatch |
| `0x06` | `ERR_TUNE_FAIL` | Tune operation failed | | `0x06` | `ERR_TUNE_FAIL` | Tune operation failed |
| `0x07` | `ERR_EP0_TIMEOUT` | EP0 data phase timeout or short payload | | `0x07` | `ERR_EP0_TIMEOUT` | EP0 data phase timeout or short payload |
| `0x08` | `ERR_GPIF_TIMEOUT` | GPIF did not reach idle state | | `0x08` | `ERR_GPIF_TIMEOUT` | GPIF did not reach idle state |
| `0x09` | `ERR_EP2_TIMEOUT` | EP2 FIFO full timeout during sweep | | `0x09` | `ERR_EP2_TIMEOUT` | EP2 FIFO full timeout during sweep |
| `0x0A` | `ERR_NOT_SUPPORTED` | Operation not supported (e.g., tone burst B) | | `0x0A` | `ERR_NOT_SUPPORTED` | Operation not supported (e.g., tone burst B) |
| `0x0B` | `ERR_DISEQC_LEN` | DiSEqC message length invalid | | `0x0B` | `ERR_DISEQC_LEN` | DiSEqC message length invalid |
| `0x0C` | `ERR_DISEQC_TIMER` | Timer2 overflow timeout during DiSEqC | | `0x0C` | `ERR_DISEQC_TIMER` | Timer2 overflow timeout during DiSEqC |
| `0x0D` | `ERR_WDT_FIRED` | Watchdog fired — LNB power was cut | | `0x0D` | `ERR_WDT_FIRED` | Watchdog fired — LNB power was cut |
## I2C Return-Value Checks ## I2C Return-Value Checks
All I2C write operations in sweep and scan functions now check return values. Failed writes skip to the next iteration instead of proceeding with stale data: All I2C write operations in sweep and scan functions now check return values. Failed writes skip to the next iteration instead of proceeding with stale data:
- `do_param_sweep()` — `bcm_indirect_write_block()` and `bcm_direct_write()` calls - `do_param_sweep()` — `bcm_indirect_write_block()` and `bcm_direct_write()` calls
- `do_spectrum_sweep()` — `bcm_indirect_write_block()` calls - `do_spectrum_sweep()` — `bcm_indirect_write_block()` calls
- `do_blind_scan()` — `bcm_indirect_write_block()` and `bcm_direct_write()` calls - `do_blind_scan()` — `bcm_indirect_write_block()` and `bcm_direct_write()` calls
- `do_adaptive_blind_scan()` — same pattern - `do_adaptive_blind_scan()` — same pattern
## do_tune() Safety ## do_tune() Safety
The `do_tune()` function was the most dangerous code path — it performed a 12-byte I2C write using the fx2lib `i2c_write()` function, which has no timeout protection. In v3.05.0: The `do_tune()` function was the most dangerous code path — it performed a 12-byte I2C write using the fx2lib `i2c_write()` function, which has no timeout protection. In v3.05.0:
- The fx2lib `i2c_write()` call is replaced with `i2c_write_multi_timeout()`, which applies the standard I2C timeout to every byte - The fx2lib `i2c_write()` call is replaced with `i2c_write_multi_timeout()`, which applies the standard I2C timeout to every byte
- Both `bcm_poll_ready()` calls check their return values - Both `bcm_poll_ready()` calls check their return values
- Both `bcm_direct_write()` calls check their return values - Both `bcm_direct_write()` calls check their return values
- An early guard rejects the tune if the BCM4500 is not booted (`ERR_BCM_NOT_READY`) - An early guard rejects the tune if the BCM4500 is not booted (`ERR_BCM_NOT_READY`)
## DiSEqC Safety ## DiSEqC Safety
- **Tone burst B** is explicitly rejected with `ERR_NOT_SUPPORTED` — the hardware only supports tone burst A (unmodulated carrier) - **Tone burst B** is explicitly rejected with `ERR_NOT_SUPPORTED` — the hardware only supports tone burst A (unmodulated carrier)
- **Invalid message lengths** (&lt;3 or &gt;6 bytes) set `ERR_DISEQC_LEN` - **Invalid message lengths** (&lt;3 or &gt;6 bytes) set `ERR_DISEQC_LEN`
- **Timer2 waits** in `diseqc_wait_ticks()` have per-tick timeout protection — a stuck Timer2 no longer hangs the firmware - **Timer2 waits** in `diseqc_wait_ticks()` have per-tick timeout protection — a stuck Timer2 no longer hangs the firmware
- `diseqc_tone_burst()` was refactored to use `diseqc_wait_ticks()` instead of three separate bare `while (!TF2)` loops - `diseqc_tone_burst()` was refactored to use `diseqc_wait_ticks()` instead of three separate bare `while (!TF2)` loops
## Other Fixes ## Other Fixes
| Fix | Description | | Fix | Description |
|-----|-------------| |-----|-------------|
| `hp_changes` saturation | Counter capped at 0xFFFF to prevent u16 wrap-around | | `hp_changes` saturation | Counter capped at 0xFFFF to prevent u16 wrap-around |
| `stream_diag_poll()` | Only updates `sd_last_status` / `sd_last_lock` on successful I2C reads | | `stream_diag_poll()` | Only updates `sd_last_status` / `sd_last_lock` on successful I2C reads |
| `BCM_LOCK_BIT` constant | Replaces 4 hardcoded `0x20` literals with named constant | | `BCM_LOCK_BIT` constant | Replaces 4 hardcoded `0x20` literals with named constant |
| Hotplug data integrity | `hp_prev` bitmap is only updated after a successful scan completes | | Hotplug data integrity | `hp_prev` bitmap is only updated after a successful scan completes |
| EP0BUF zero-fill | Commands 0x87 and 0xB7 zero-fill EP0BUF before indirect reads, ensuring I2C failures return zeros instead of stale buffer contents | | EP0BUF zero-fill | Commands 0x87 and 0xB7 zero-fill EP0BUF before indirect reads, ensuring I2C failures return zeros instead of stale buffer contents |
## Memory Budget ## Memory Budget
``` ```
Code: 13,079 / 15,360 bytes (85%) +948 bytes from v3.04 Code: 13,079 / 15,360 bytes (85%) +948 bytes from v3.04
XRAM: 218 / 512 bytes (43%) +2 bytes (wdt_counter, wdt_armed) XRAM: 218 / 512 bytes (43%) +2 bytes (wdt_counter, wdt_armed)
Stack: 132 bytes available unchanged Stack: 132 bytes available unchanged
``` ```
The safety additions cost 948 bytes of code space — well within the 2,281-byte margin. The 8051 stack starts at `0x7C` with 132 bytes, which is sufficient for the deepest call chain (vendor command → sweep → I2C helpers → Timer0 ISR). The safety additions cost 948 bytes of code space — well within the 2,281-byte margin. The 8051 stack starts at `0x7C` with 132 bytes, which is sufficient for the deepest call chain (vendor command → sweep → I2C helpers → Timer0 ISR).
## Hardware Validation ## Hardware Validation
Firmware v3.05.0 was loaded onto physical hardware and tested: Firmware v3.05.0 was loaded onto physical hardware and tested:
| Test | Result | | Test | Result |
|------|--------| |------|--------|
| Firmware load + re-enumeration | Pass | | Firmware load + re-enumeration | Pass |
| Version readback (0x92) | `v3.05.0 (2026-02-16)` | | Version readback (0x92) | `v3.05.0 (2026-02-16)` |
| BCM4500 boot (0x89) | `STARTED \| FW_LOADED`, stage `COMPLETE` | | BCM4500 boot (0x89) | `STARTED \| FW_LOADED`, stage `COMPLETE` |
| I2C bus scan (0xB4) | Found BCM4500 (0x08), tuner (0x10), EEPROM (0x51) | | I2C bus scan (0xB4) | Found BCM4500 (0x08), tuner (0x10), EEPROM (0x51) |
| Spectrum sweep (9502150 MHz) | 121 points, no hang | | Spectrum sweep (9502150 MHz) | 121 points, no hang |
| LNB power control (13V/18V/22kHz) | All config bits track correctly | | LNB power control (13V/18V/22kHz) | All config bits track correctly |
| DiSEqC 1.0 switch | No error | | DiSEqC 1.0 switch | No error |
| DiSEqC tone burst A | No error | | DiSEqC tone burst A | No error |
| DiSEqC 1.2 motor commands | No error | | DiSEqC 1.2 motor commands | No error |
| Tune attempt (no signal) | No hang, `last_error` stays OK | | Tune attempt (no signal) | No hang, `last_error` stays OK |
| Signal monitor (no signal) | 0.0 dB SNR, no lock | | Signal monitor (no signal) | 0.0 dB SNR, no lock |
| Adversarial test suite | 55/55 passed | | Adversarial test suite | 55/55 passed |
| Watchdog false-fire | None observed | | Watchdog false-fire | None observed |
See [Safety Testing](/tools/safety-testing/) for the full adversarial test methodology and results. See [Safety Testing](/tools/safety-testing/) for the full adversarial test methodology and results.
## What Changed from v3.04 ## What Changed from v3.04
| Feature | v3.04 | v3.05 | | Feature | v3.04 | v3.05 |
|---------|-------|-------| |---------|-------|-------|
| Software watchdog | None | Timer0-based, 2-second window | | Software watchdog | None | Timer0-based, 2-second window |
| I2C timeout paths | Helpers only | All paths including bus scan, DiSEqC | | I2C timeout paths | Helpers only | All paths including bus scan, DiSEqC |
| EP0 BUSY protection | None (bare spin) | `ep0_wait_data()` with timeout | | EP0 BUSY protection | None (bare spin) | `ep0_wait_data()` with timeout |
| GPIF idle protection | None (bare spin) | Timeout with `ERR_GPIF_TIMEOUT` | | GPIF idle protection | None (bare spin) | Timeout with `ERR_GPIF_TIMEOUT` |
| EP2 full protection | None (bare spin) | Timeout with `ERR_EP2_TIMEOUT` | | EP2 full protection | None (bare spin) | Timeout with `ERR_EP2_TIMEOUT` |
| `do_tune()` I2C | fx2lib `i2c_write()` (no timeout) | `i2c_write_multi_timeout()` | | `do_tune()` I2C | fx2lib `i2c_write()` (no timeout) | `i2c_write_multi_timeout()` |
| Error codes | 6 (`0x00``0x05`) | 14 (`0x00``0x0D`) | | Error codes | 6 (`0x00``0x05`) | 14 (`0x00``0x0D`) |
| Payload validation | None | EP0BCL checked against expected size | | Payload validation | None | EP0BCL checked against expected size |
| DiSEqC Timer2 | Bare `while (!TF2)` | Timeout-protected `diseqc_wait_ticks()` | | DiSEqC Timer2 | Bare `while (!TF2)` | Timeout-protected `diseqc_wait_ticks()` |
| Sweep I2C checks | Unchecked writes | Returns checked, `continue` on fail | | Sweep I2C checks | Unchecked writes | Returns checked, `continue` on fail |
| Adversarial testing | None | 55-test Hamilton suite | | Adversarial testing | None | 55-test Hamilton suite |

View File

@ -1,243 +1,243 @@
--- ---
title: FW2.13 Sub-Variant Comparison title: FW2.13 Sub-Variant Comparison
description: Binary and functional comparison of v2.13 firmware sub-variants FW1, FW2, and FW3. description: Binary and functional comparison of v2.13 firmware sub-variants FW1, FW2, and FW3.
--- ---
import { Tabs, TabItem, Badge, Aside } from '@astrojs/starlight/components'; import { Tabs, TabItem, Badge, Aside } from '@astrojs/starlight/components';
The v2.13 firmware was distributed as three sub-variants via the `SW1_update_2_13_x.exe` Windows updater tool. Ghidra analysis reveals that these target fundamentally different hardware interfaces, not just minor revisions. The v2.13 firmware was distributed as three sub-variants via the `SW1_update_2_13_x.exe` Windows updater tool. Ghidra analysis reveals that these target fundamentally different hardware interfaces, not just minor revisions.
## Overview ## Overview
| Aspect | FW1 (v2.13.1) | FW2 (v2.13.2) | FW3 (v2.13.3) | | Aspect | FW1 (v2.13.1) | FW2 (v2.13.2) | FW3 (v2.13.3) |
|--------|---------------|---------------|---------------| |--------|---------------|---------------|---------------|
| Version ID | `0x020D01` | `0x020D01` | `0x020D01` | | Version ID | `0x020D01` | `0x020D01` | `0x020D01` |
| Build date | 2010-03-12 | 2010-03-12 | 2010-03-12 | | Build date | 2010-03-12 | 2010-03-12 | 2010-03-12 |
| Functions | 82 | 83 | 83 | | Functions | 82 | 83 | 83 |
| Binary size | 9,322 bytes | 9,377 bytes | 9,369 bytes | | Binary size | 9,322 bytes | 9,377 bytes | 9,369 bytes |
| Stack pointer | `0x50` | `0x50` | **`0x52`** | | Stack pointer | `0x50` | `0x50` | **`0x52`** |
| P0 init | `0xA4` | `0xA4` | **`0xA0`** | | P0 init | `0xA4` | `0xA4` | **`0xA0`** |
| Status register | INTMEM `0x4F` | INTMEM `0x4F` | **INTMEM `0x51`** | | Status register | INTMEM `0x4F` | INTMEM `0x4F` | **INTMEM `0x51`** |
| Demod interface | **I2C bus** | **Parallel bus (P0/P1)** | **Parallel bus (enhanced)** | | Demod interface | **I2C bus** | **Parallel bus (P0/P1)** | **Parallel bus (enhanced)** |
| Config source | Hardcoded | External (`0xE080`--`0xE08E`) | External (`0xE080`--`0xE08E`) | | Config source | Hardcoded | External (`0xE080`--`0xE08E`) | External (`0xE080`--`0xE08E`) |
## Hardware Detection ## Hardware Detection
All three sub-variants report the same version ID (`0x020D01`) to the host. The Windows updater `SW1_update_2_13_x.exe` selects which sub-variant to flash, but the detection mechanism is not yet fully understood. All three sub-variants report the same version ID (`0x020D01`) to the host. The Windows updater `SW1_update_2_13_x.exe` selects which sub-variant to flash, but the detection mechanism is not yet fully understood.
<Aside type="caution" title="Open Investigation"> <Aside type="caution" title="Open Investigation">
The exact hardware detection method remains unknown. The updater binary has not been fully disassembled. Candidates include a GPIO strap read (cheap, common in consumer electronics), an I2C device ID probe (the demod responds differently on I2C vs. parallel-bus hardware), or a USB descriptor field that encodes the PCB revision. If you have access to the updater binary or multiple hardware revisions, this would be a valuable area to investigate. The exact hardware detection method remains unknown. The updater binary has not been fully disassembled. Candidates include a GPIO strap read (cheap, common in consumer electronics), an I2C device ID probe (the demod responds differently on I2C vs. parallel-bus hardware), or a USB descriptor field that encodes the PCB revision. If you have access to the updater binary or multiple hardware revisions, this would be a valuable area to investigate.
</Aside> </Aside>
### Distinguishing Characteristics ### Distinguishing Characteristics
Although the updater's detection method is opaque, the firmware binaries themselves contain clear markers that distinguish each target hardware: Although the updater's detection method is opaque, the firmware binaries themselves contain clear markers that distinguish each target hardware:
| Characteristic | FW1 | FW2 | FW3 | Docs | | Characteristic | FW1 | FW2 | FW3 | Docs |
|---------------|-----|-----|-----|------| |---------------|-----|-----|-----|------|
| P0 init value | `0xA4` | `0xA4` | `0xA0` (bit 2 cleared) | [Register Map &mdash; IRAM](/bcm4500/register-map/#fx2-iram-by-firmware-version) | | P0 init value | `0xA4` | `0xA4` | `0xA0` (bit 2 cleared) | [Register Map &mdash; IRAM](/bcm4500/register-map/#fx2-iram-by-firmware-version) |
| Stack pointer | `0x50` | `0x50` | `0x52` (+2 for status reg) | [Register Map &mdash; IRAM](/bcm4500/register-map/#fx2-iram-by-firmware-version) | | Stack pointer | `0x50` | `0x50` | `0x52` (+2 for status reg) | [Register Map &mdash; IRAM](/bcm4500/register-map/#fx2-iram-by-firmware-version) |
| Config status IRAM | `0x4F` | `0x4F` | `0x51` | [Config Status](/usb/config-status/) | | Config status IRAM | `0x4F` | `0x4F` | `0x51` | [Config Status](/usb/config-status/) |
| I2C buffer IRAM | `0x48`/`0x49` | `0x48`/`0x49` | `0x4A`/`0x4B` | [Register Map &mdash; IRAM](/bcm4500/register-map/#fx2-iram-by-firmware-version) | | I2C buffer IRAM | `0x48`/`0x49` | `0x48`/`0x49` | `0x4A`/`0x4B` | [Register Map &mdash; IRAM](/bcm4500/register-map/#fx2-iram-by-firmware-version) |
| Demod interface | I2C bus | Parallel (P0/P1) | Parallel (enhanced, dual-phase) | See tabs below | | Demod interface | I2C bus | Parallel (P0/P1) | Parallel (enhanced, dual-phase) | See tabs below |
| Config source | Hardcoded | External `0xE080`--`0xE08E` | External `0xE080`--`0xE08E` | [Register Map &mdash; XRAM](/bcm4500/register-map/#fw2fw3-external-configuration) | | Config source | Hardcoded | External `0xE080`--`0xE08E` | External `0xE080`--`0xE08E` | [Register Map &mdash; XRAM](/bcm4500/register-map/#fw2fw3-external-configuration) |
### FW1 Demod Type Detection ### FW1 Demod Type Detection
FW1 is the only sub-variant that performs demodulator type identification at runtime. Function `FUN_CODE_1405` reads the P1 port after an I2C transaction and matches the result against known silicon signatures: FW1 is the only sub-variant that performs demodulator type identification at runtime. Function `FUN_CODE_1405` reads the P1 port after an I2C transaction and matches the result against known silicon signatures:
| Type Code | P1 Signature | Likely Silicon | | Type Code | P1 Signature | Likely Silicon |
|-----------|--------------|----------------| |-----------|--------------|----------------|
| Type 3 | `0xA5` or `0xB5` | Original BCM4500 | | Type 3 | `0xA5` or `0xB5` | Original BCM4500 |
| Type 4 | `0x5A` | BCM4500 revision A | | Type 4 | `0x5A` | BCM4500 revision A |
| Type 5 | `0x5B` | BCM4500 revision B | | Type 5 | `0x5B` | BCM4500 revision B |
| Type 6 | `0x5C` | BCM4500 revision C | | Type 6 | `0x5C` | BCM4500 revision C |
FW2 and FW3 use a different signature check (`P1 ^ 0x1D`) through the parallel bus, suggesting the demod variant is already known at flash time on those PCBs. FW2 and FW3 use a different signature check (`P1 ^ 0x1D`) through the parallel bus, suggesting the demod variant is already known at flash time on those PCBs.
## Hardware Interface Evolution ## Hardware Interface Evolution
<Tabs> <Tabs>
<TabItem label="FW1 -- I2C Bus"> <TabItem label="FW1 -- I2C Bus">
### FW1 (v2.13.1) <Badge text="I2C" variant="note" /> ### FW1 (v2.13.1) <Badge text="I2C" variant="note" />
FW1 targets the original SkyWalker-1 PCB with an **I2C-connected demodulator**. The FX2 communicates with the demod entirely through standard I2C master-mode transactions. FW1 targets the original SkyWalker-1 PCB with an **I2C-connected demodulator**. The FX2 communicates with the demod entirely through standard I2C master-mode transactions.
**Evidence from `FUN_CODE_0eea`:** **Evidence from `FUN_CODE_0eea`:**
- Uses `FUN_CODE_23ae` (I2C START), `FUN_CODE_23ee` (I2C byte write), `FUN_CODE_23d0` (I2C address) - Uses `FUN_CODE_23ae` (I2C START), `FUN_CODE_23ee` (I2C byte write), `FUN_CODE_23d0` (I2C address)
- Standard I2C retry with NACK detection - Standard I2C retry with NACK detection
- Timer2-based I2C timeout (TR2 check in vendor handler) - Timer2-based I2C timeout (TR2 check in vendor handler)
- Reads back via `FUN_CODE_2164` - Reads back via `FUN_CODE_2164`
**Unique functions:** **Unique functions:**
- `FUN_CODE_0fc7` -- I2C write-with-retry (20 attempts via I2C bus) - `FUN_CODE_0fc7` -- I2C write-with-retry (20 attempts via I2C bus)
- `FUN_CODE_1405` -- Tuner/demodulator identification via I2C + P1 port reads with signature matching - `FUN_CODE_1405` -- Tuner/demodulator identification via I2C + P1 port reads with signature matching
- `FUN_CODE_14b9` -- Calibrated delay function with CPUCS clock divider awareness - `FUN_CODE_14b9` -- Calibrated delay function with CPUCS clock divider awareness
**Demodulator type detection** (from `FUN_CODE_1405`): **Demodulator type detection** (from `FUN_CODE_1405`):
| Type Code | P1 Signature | | Type Code | P1 Signature |
|-----------|--------------| |-----------|--------------|
| Type 3 | `0xA5` or `0xB5` | | Type 3 | `0xA5` or `0xB5` |
| Type 4 | `0x5A` | | Type 4 | `0x5A` |
| Type 5 | `0x5B` | | Type 5 | `0x5B` |
| Type 6 | `0x5C` | | Type 6 | `0x5C` |
</TabItem> </TabItem>
<TabItem label="FW2 -- Parallel Bus"> <TabItem label="FW2 -- Parallel Bus">
### FW2 (v2.13.2) <Badge text="Parallel" variant="caution" /> ### FW2 (v2.13.2) <Badge text="Parallel" variant="caution" />
FW2 targets a revised PCB with a **parallel-bus connected demodulator**. The demod data port is connected directly to the FX2's P1, with P0 bits controlling bus signals. FW2 targets a revised PCB with a **parallel-bus connected demodulator**. The demod data port is connected directly to the FX2's P1, with P0 bits controlling bus signals.
**Evidence from `FUN_CODE_0eea`:** **Evidence from `FUN_CODE_0eea`:**
- Reads demod type from address table (BANK1 pointer + offset) - Reads demod type from address table (BANK1 pointer + offset)
- Uses `FUN_CODE_11b6` for demod selection - Uses `FUN_CODE_11b6` for demod selection
- Toggles P0 bits 6/7 for bus control (P0.6 = chip select, P0.7 = read strobe) - Toggles P0 bits 6/7 for bus control (P0.6 = chip select, P0.7 = read strobe)
- Reads data from **P1 port** (8-bit parallel data bus) - Reads data from **P1 port** (8-bit parallel data bus)
- Single-phase read: one P1 read per bus cycle - Single-phase read: one P1 read per bus cycle
**Bus protocol (decompiled):** **Bus protocol (decompiled):**
```c title="FW2 parallel bus read" ```c title="FW2 parallel bus read"
uVar1 = P1; // Read data with one bus state uVar1 = P1; // Read data with one bus state
P0 |= 0x40; // Change control line P0 |= 0x40; // Change control line
uVar2 = P1; // Read again with new state uVar2 = P1; // Read again with new state
FUN_CODE_1b2a(uVar2, uVar1); // Process both samples FUN_CODE_1b2a(uVar2, uVar1); // Process both samples
``` ```
**Configuration loading:** **Configuration loading:**
- Loads 15 configuration bytes from external memory (`0xE080`--`0xE08E`) into demod registers (`0xE6C0`--`0xE6CD`) - Loads 15 configuration bytes from external memory (`0xE080`--`0xE08E`) into demod registers (`0xE6C0`--`0xE6CD`)
- Same device signature matching as FW1 but via parallel bus (`P1 ^ 0x1D` check) - Same device signature matching as FW1 but via parallel bus (`P1 ^ 0x1D` check)
</TabItem> </TabItem>
<TabItem label="FW3 -- Enhanced Parallel"> <TabItem label="FW3 -- Enhanced Parallel">
### FW3 (v2.13.3) <Badge text="Enhanced" variant="success" /> ### FW3 (v2.13.3) <Badge text="Enhanced" variant="success" />
FW3 targets a further revised PCB with the same parallel-bus architecture as FW2 but with a **different bus timing protocol**. Uses dual-phase reads with OR-accumulation. FW3 targets a further revised PCB with the same parallel-bus architecture as FW2 but with a **different bus timing protocol**. Uses dual-phase reads with OR-accumulation.
**Evidence from `FUN_CODE_0eea`:** **Evidence from `FUN_CODE_0eea`:**
- Initializes OR-accumulators: `DAT_INTMEM_3f = 0; DAT_INTMEM_40 = 0` - Initializes OR-accumulators: `DAT_INTMEM_3f = 0; DAT_INTMEM_40 = 0`
- Sets P0 | 0x80 once at start (not per-iteration like FW2) - Sets P0 | 0x80 once at start (not per-iteration like FW2)
- Two separate P1 reads per cycle with different P0.6 states - Two separate P1 reads per cycle with different P0.6 states
- OR-accumulates results before processing - OR-accumulates results before processing
**Bus protocol (decompiled):** **Bus protocol (decompiled):**
```c title="FW3 dual-phase parallel bus read" ```c title="FW3 dual-phase parallel bus read"
DAT_INTMEM_3f = 0; DAT_INTMEM_3f = 0;
DAT_INTMEM_40 = 0; // Clear accumulators DAT_INTMEM_40 = 0; // Clear accumulators
// Phase 1: P0.6 high // Phase 1: P0.6 high
P0 |= 0x44; P0 |= 0x44;
bVar2 = P1; bVar2 = P1;
DAT_INTMEM_3f |= bVar2; // OR-accumulate DAT_INTMEM_3f |= bVar2; // OR-accumulate
// Phase 2: P0.6 low // Phase 2: P0.6 low
P0 &= ~0x40; P0 &= ~0x40;
bVar2 = P1; bVar2 = P1;
DAT_INTMEM_40 |= bVar2; // OR-accumulate DAT_INTMEM_40 |= bVar2; // OR-accumulate
FUN_CODE_1b2a(0, DAT_INTMEM_3f, DAT_INTMEM_40); FUN_CODE_1b2a(0, DAT_INTMEM_3f, DAT_INTMEM_40);
``` ```
**Why OR-accumulation?** This pattern suggests the demod chip variant has either: **Why OR-accumulation?** This pattern suggests the demod chip variant has either:
- Open-drain outputs requiring multiple read cycles - Open-drain outputs requiring multiple read cycles
- Bus settling time issues on the newer PCB layout - Bus settling time issues on the newer PCB layout
- A chip revision that serializes data across multiple bus phases - A chip revision that serializes data across multiple bus phases
</TabItem> </TabItem>
</Tabs> </Tabs>
## Binary Distance Matrix ## Binary Distance Matrix
Byte-level differences between sub-variants: Byte-level differences between sub-variants:
| Pair | Different Bytes | Percentage Different | | Pair | Different Bytes | Percentage Different |
|------|----------------:|---------------------:| |------|----------------:|---------------------:|
| FW1 vs FW2 | 3,993 | 42.8% | | FW1 vs FW2 | 3,993 | 42.8% |
| FW1 vs FW3 | 3,789 | 40.6% | | FW1 vs FW3 | 3,789 | 40.6% |
| FW2 vs FW3 | **1,525** | **16.5%** | | FW2 vs FW3 | **1,525** | **16.5%** |
FW2 and FW3 are 83.5% identical at the byte level, confirming they share the same parallel-bus architecture. FW1 diverges significantly because it uses a completely different bus interface (I2C vs. parallel). FW2 and FW3 are 83.5% identical at the byte level, confirming they share the same parallel-bus architecture. FW1 diverges significantly because it uses a completely different bus interface (I2C vs. parallel).
## Memory Comparison at Key Offsets ## Memory Comparison at Key Offsets
### Identical Regions ### Identical Regions
These regions are byte-identical across all three sub-variants: These regions are byte-identical across all three sub-variants:
| Address Range | Content | | Address Range | Content |
|---------------|---------| |---------------|---------|
| `0x0000`--`0x000F` | RESET vector (`LJMP 0x170D`), INT0 handler | | `0x0000`--`0x000F` | RESET vector (`LJMP 0x170D`), INT0 handler |
| `0x0B88`--`0x0B9F` | Init table (same XRAM register initialization) | | `0x0B88`--`0x0B9F` | Init table (same XRAM register initialization) |
| `0x06D9`--`0x06F0` | Generic memory access utilities | | `0x06D9`--`0x06F0` | Generic memory access utilities |
| `0x1740`--`0x174F` | Bit manipulation lookup table | | `0x1740`--`0x174F` | Bit manipulation lookup table |
### Critical Divergence: `CODE:0EEA` ### Critical Divergence: `CODE:0EEA`
This is where the three sub-variants diverge most dramatically: This is where the three sub-variants diverge most dramatically:
``` ```
FW1: 8f44 8c45 8d46 8b47 754a14 e544 b451... FW1: 8f44 8c45 8d46 8b47 754a14 e544 b451...
(I2C transfer parameters in registers) (I2C transfer parameters in registers)
FW2: 753e14 e50d 240a f582 e435 0cf5 83e0... FW2: 753e14 e50d 240a f582 e435 0cf5 83e0...
(reads from DPTR+offset table) (reads from DPTR+offset table)
FW3: 753e14 e4f5 3ff5 40 e50d 240a f582... FW3: 753e14 e4f5 3ff5 40 e50d 240a f582...
(similar to FW2 + accumulator initialization) (similar to FW2 + accumulator initialization)
``` ```
FW1's `FUN_CODE_0eea` is a standard I2C master transfer function. FW2/FW3's version is a parallel bus demodulator interface. FW1's `FUN_CODE_0eea` is a standard I2C master transfer function. FW2/FW3's version is a parallel bus demodulator interface.
### Thunk Target Divergence (`CODE:1500`) ### Thunk Target Divergence (`CODE:1500`)
``` ```
FW1: 02 2252 00 02 22dd 00 02 22c7 00 02 226a 00 FW1: 02 2252 00 02 22dd 00 02 22c7 00 02 226a 00
FW2: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00 FW2: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00
FW3: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00 FW3: 02 228d 00 02 2318 00 02 2302 00 02 22a5 00
``` ```
FW2 and FW3 share identical interrupt handler targets. FW1 jumps to different addresses, reflecting its different internal function layout. FW2 and FW3 share identical interrupt handler targets. FW1 jumps to different addresses, reflecting its different internal function layout.
## Detailed Differences ## Detailed Differences
### Stack Pointer and Status Register ### Stack Pointer and Status Register
| Property | FW1 | FW2 | FW3 | | Property | FW1 | FW2 | FW3 |
|----------|-----|-----|-----| |----------|-----|-----|-----|
| SP value | `0x50` | `0x50` | `0x52` | | SP value | `0x50` | `0x50` | `0x52` |
| Status IRAM | `0x4F` | `0x4F` | `0x51` | | Status IRAM | `0x4F` | `0x4F` | `0x51` |
| I2C buffer IRAM | `0x48`/`0x49` | `0x48`/`0x49` | `0x4A`/`0x4B` | | I2C buffer IRAM | `0x48`/`0x49` | `0x48`/`0x49` | `0x4A`/`0x4B` |
FW3 pushes the stack pointer up by 2 bytes to make room for the additional status register at IRAM `0x51`. The 2-byte SP difference exactly accounts for moving the status register from `0x4F` to `0x51`. FW3 pushes the stack pointer up by 2 bytes to make room for the additional status register at IRAM `0x51`. The 2-byte SP difference exactly accounts for moving the status register from `0x4F` to `0x51`.
### P0 Init Value ### P0 Init Value
| Variant | P0 Init | Binary | Difference | | Variant | P0 Init | Binary | Difference |
|---------|---------|--------|------------| |---------|---------|--------|------------|
| FW1/FW2 | `0xA4` | `1010 0100` | Bit 2 = 1 | | FW1/FW2 | `0xA4` | `1010 0100` | Bit 2 = 1 |
| FW3 | `0xA0` | `1010 0000` | Bit 2 = 0 | | FW3 | `0xA0` | `1010 0000` | Bit 2 = 0 |
P0 bit 2 controls a GPIO signal likely related to demodulator interface mode or reset polarity on the FW3 target PCB. P0 bit 2 controls a GPIO signal likely related to demodulator interface mode or reset polarity on the FW3 target PCB.
### Vendor Handler Differences ### Vendor Handler Differences
| Feature | FW1 | FW2/FW3 | | Feature | FW1 | FW2/FW3 |
|---------|-----|---------| |---------|-----|---------|
| Case `0x3D3` | TR2 timer check (I2C timeout) | OR operation (parallel bus) | | Case `0x3D3` | TR2 timer check (I2C timeout) | OR operation (parallel bus) |
| Case `0x421`-`0x423` | Simple check | P2.1 write + rotate-left (bus direction) | | Case `0x421`-`0x423` | Simple check | P2.1 write + rotate-left (bus direction) |
| Error path | `func_0x06e4` | `DAT=0x0` | | Error path | `func_0x06e4` | `DAT=0x0` |
FW1's timer-based case is used for I2C bus timeout recovery. FW2/FW3's rotate-left and P2.1 write is a parallel bus data direction control. FW1's timer-based case is used for I2C bus timeout recovery. FW2/FW3's rotate-left and P2.1 write is a parallel bus data direction control.
## Hardware Progression Theory ## Hardware Progression Theory
The three sub-variants represent an evolutionary progression: The three sub-variants represent an evolutionary progression:
1. **FW1 (v2.13.1)**: Original design with I2C-connected demodulator. Simple interface but limited in bandwidth. The FX2 acts purely as an I2C master bridge. 1. **FW1 (v2.13.1)**: Original design with I2C-connected demodulator. Simple interface but limited in bandwidth. The FX2 acts purely as an I2C master bridge.
2. **FW2 (v2.13.2)**: Redesigned with parallel-bus demodulator for higher throughput. P1 carries 8-bit data, P0 provides control signals. External calibration data at `0xE080`--`0xE08E`. 2. **FW2 (v2.13.2)**: Redesigned with parallel-bus demodulator for higher throughput. P1 carries 8-bit data, P0 provides control signals. External calibration data at `0xE080`--`0xE08E`.
3. **FW3 (v2.13.3)**: Refined parallel interface for a newer demod silicon revision. Dual-phase reads with OR-accumulation handle bus timing differences. Additional IRAM state tracking (SP bumped to `0x52`). 3. **FW3 (v2.13.3)**: Refined parallel interface for a newer demod silicon revision. Dual-phase reads with OR-accumulation handle bus timing differences. Additional IRAM state tracking (SP bumped to `0x52`).
All three support the same modulation types (DVB-S QPSK, Turbo QPSK/8PSK/16QAM, DCII, DSS) and the same demod type codes (3--6). The differences are purely hardware interface, not feature set. All three support the same modulation types (DVB-S QPSK, Turbo QPSK/8PSK/16QAM, DCII, DSS) and the same demod type codes (3--6). The differences are purely hardware interface, not feature set.

View File

@ -1,184 +1,184 @@
--- ---
title: Kernel FW01 Analysis title: Kernel FW01 Analysis
description: Analysis of the dvb-usb-gp8psk-01.fw firmware format, loading mechanism, and why SkyWalker-1 does not need it. description: Analysis of the dvb-usb-gp8psk-01.fw firmware format, loading mechanism, and why SkyWalker-1 does not need it.
--- ---
import { Steps, Badge, Aside, Tabs, TabItem, FileTree } from '@astrojs/starlight/components'; import { Steps, Badge, Aside, Tabs, TabItem, FileTree } from '@astrojs/starlight/components';
The Linux kernel `dvb_usb_gp8psk` driver references two firmware files: `dvb-usb-gp8psk-01.fw` (FX2 microcontroller code) and `dvb-usb-gp8psk-02.fw` (BCM4500 demodulator code). Neither file was ever open-sourced or included in the `linux-firmware` repository. The SkyWalker-1 does not need them. The Linux kernel `dvb_usb_gp8psk` driver references two firmware files: `dvb-usb-gp8psk-01.fw` (FX2 microcontroller code) and `dvb-usb-gp8psk-02.fw` (BCM4500 demodulator code). Neither file was ever open-sourced or included in the `linux-firmware` repository. The SkyWalker-1 does not need them.
## Firmware File Status ## Firmware File Status
| File | Purpose | Available? | Needed by SkyWalker-1? | | File | Purpose | Available? | Needed by SkyWalker-1? |
|------|---------|------------|----------------------| |------|---------|------------|----------------------|
| `dvb-usb-gp8psk-01.fw` | FX2 RAM code | **Not in linux-firmware** | No | | `dvb-usb-gp8psk-01.fw` | FX2 RAM code | **Not in linux-firmware** | No |
| `dvb-usb-gp8psk-02.fw` | BCM4500 demod code | **Not in linux-firmware** | No | | `dvb-usb-gp8psk-02.fw` | BCM4500 demod code | **Not in linux-firmware** | No |
Standard locations checked: Standard locations checked:
| Path | Result | | Path | Result |
|------|--------| |------|--------|
| `/lib/firmware/dvb-usb-gp8psk-01.fw` | Not found | | `/lib/firmware/dvb-usb-gp8psk-01.fw` | Not found |
| `/lib/firmware/dvb-usb-gp8psk-02.fw` | Not found | | `/lib/firmware/dvb-usb-gp8psk-02.fw` | Not found |
| `linux-firmware` WHENCE manifest | No gp8psk entry | | `linux-firmware` WHENCE manifest | No gp8psk entry |
| Kernel `scripts/get_dvb_firmware` | No gp8psk handler | | Kernel `scripts/get_dvb_firmware` | No gp8psk handler |
| `pacman -F dvb-usb-gp8psk-01.fw` | No package provides it | | `pacman -F dvb-usb-gp8psk-01.fw` | No package provides it |
<Aside type="note"> <Aside type="note">
The gp8psk firmware was presumably distributed by Genpix Electronics with their Windows BDA driver installer. It was never contributed to the Linux firmware collection. The gp8psk firmware was presumably distributed by Genpix Electronics with their Windows BDA driver installer. It was never contributed to the Linux firmware collection.
</Aside> </Aside>
## Why SkyWalker-1 Works Without Firmware Files ## Why SkyWalker-1 Works Without Firmware Files
The answer is in the kernel driver's device table. Only Rev.1 Cold devices (PID `0x0200`) have a `cold_ids` entry, which triggers firmware download: The answer is in the kernel driver's device table. Only Rev.1 Cold devices (PID `0x0200`) have a `cold_ids` entry, which triggers firmware download:
```c title="Kernel device properties (from gp8psk.c)" ```c title="Kernel device properties (from gp8psk.c)"
.devices = { .devices = {
{ .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver", { .name = "Genpix 8PSK-to-USB2 Rev.1 DVB-S receiver",
.cold_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_COLD], NULL }, .cold_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_COLD], NULL },
.warm_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_WARM], NULL }, .warm_ids = { &gp8psk_usb_table[GENPIX_8PSK_REV_1_WARM], NULL },
}, },
{ .name = "Genpix SkyWalker-1 DVB-S receiver", { .name = "Genpix SkyWalker-1 DVB-S receiver",
.cold_ids = { NULL }, // <-- NO cold_ids: skip firmware .cold_ids = { NULL }, // <-- NO cold_ids: skip firmware
.warm_ids = { &gp8psk_usb_table[GENPIX_SKYWALKER_1], NULL }, .warm_ids = { &gp8psk_usb_table[GENPIX_SKYWALKER_1], NULL },
}, },
// ... // ...
} }
``` ```
When `cold_ids` is NULL, the DVB-USB framework skips firmware download entirely. The SkyWalker-1 boots from its onboard EEPROM and enumerates directly as a "warm" device. When `cold_ids` is NULL, the DVB-USB framework skips firmware download entirely. The SkyWalker-1 boots from its onboard EEPROM and enumerates directly as a "warm" device.
| Device | PID | Needs FW01? | Needs FW02? | Boot Source | | Device | PID | Needs FW01? | Needs FW02? | Boot Source |
|--------|-----|-------------|-------------|-------------| |--------|-----|-------------|-------------|-------------|
| Rev.1 Cold | `0x0200` | **Yes** | -- | RAM (empty) | | Rev.1 Cold | `0x0200` | **Yes** | -- | RAM (empty) |
| Rev.1 Warm | `0x0201` | No | **Yes** | RAM (FW01 loaded) | | Rev.1 Warm | `0x0201` | No | **Yes** | RAM (FW01 loaded) |
| Rev.2 | `0x0202` | No | No | EEPROM | | Rev.2 | `0x0202` | No | No | EEPROM |
| SkyWalker-1 | `0x0203` | No | No | EEPROM | | SkyWalker-1 | `0x0203` | No | No | EEPROM |
| SkyWalker CW3K | `0x0206` | No | No | EEPROM | | SkyWalker CW3K | `0x0206` | No | No | EEPROM |
## FW01 Loading Mechanism ## FW01 Loading Mechanism
For Rev.1 Cold devices, the firmware loading follows this sequence: For Rev.1 Cold devices, the firmware loading follows this sequence:
<Steps> <Steps>
1. **DVB-USB framework** matches the USB VID:PID against `cold_ids` and calls `dvb_usb_download_firmware()` 1. **DVB-USB framework** matches the USB VID:PID against `cold_ids` and calls `dvb_usb_download_firmware()`
2. **Kernel requests firmware** via `request_firmware("dvb-usb-gp8psk-01.fw", ...)` from the userspace firmware loader 2. **Kernel requests firmware** via `request_firmware("dvb-usb-gp8psk-01.fw", ...)` from the userspace firmware loader
3. **Cypress FX2 loader** (`usb_cypress_load_firmware()`) halts the FX2 CPU by writing `0x01` to CPUCS register (`0xE600`) via the 0xA0 vendor request 3. **Cypress FX2 loader** (`usb_cypress_load_firmware()`) halts the FX2 CPU by writing `0x01` to CPUCS register (`0xE600`) via the 0xA0 vendor request
4. **Hexline records** are parsed and written to FX2 RAM via USB control transfers (0xA0 vendor request) 4. **Hexline records** are parsed and written to FX2 RAM via USB control transfers (0xA0 vendor request)
5. **FX2 CPU restarted** by writing `0x00` to CPUCS. The device re-enumerates with a new PID (0x0201, "warm") 5. **FX2 CPU restarted** by writing `0x00` to CPUCS. The device re-enumerates with a new PID (0x0201, "warm")
6. **DVB-USB framework** re-matches the new PID against `warm_ids` and proceeds to frontend attach 6. **DVB-USB framework** re-matches the new PID against `warm_ids` and proceeds to frontend attach
</Steps> </Steps>
The 0xA0 vendor request is handled by the FX2's built-in silicon boot ROM, which provides RAM read/write access regardless of whether user firmware is running. This is the same mechanism used by the custom firmware's `fw_load.py` tool. The 0xA0 vendor request is handled by the FX2's built-in silicon boot ROM, which provides RAM read/write access regardless of whether user firmware is running. This is the same mechanism used by the custom firmware's `fw_load.py` tool.
## FW01 Binary Hexline Format ## FW01 Binary Hexline Format
The kernel's `dvb_usb_get_hexline()` parser expects a compact binary representation of Intel HEX records. This is **not** standard Intel HEX text (`:10000000...`), nor the kernel's `ihex_binrec` format from `<linux/ihex.h>`. The kernel's `dvb_usb_get_hexline()` parser expects a compact binary representation of Intel HEX records. This is **not** standard Intel HEX text (`:10000000...`), nor the kernel's `ihex_binrec` format from `<linux/ihex.h>`.
### Record Structure ### Record Structure
``` ```
Offset Size Field Offset Size Field
------ ---- ----- ------ ---- -----
0 1 len - Number of data bytes 0 1 len - Number of data bytes
1 1 addr_lo - Target address low byte 1 1 addr_lo - Target address low byte
2 1 addr_hi - Target address high byte 2 1 addr_hi - Target address high byte
3 1 type - Record type 3 1 type - Record type
4 len data[] - Payload bytes 4 len data[] - Payload bytes
4+len 1 chk - Checksum byte 4+len 1 chk - Checksum byte
Total per record: len + 5 bytes Total per record: len + 5 bytes
``` ```
### Record Types ### Record Types
| Type | Name | Purpose | | Type | Name | Purpose |
|------|------|---------| |------|------|---------|
| `0x00` | Data | Code/data bytes for FX2 RAM | | `0x00` | Data | Code/data bytes for FX2 RAM |
| `0x01` | EOF | End of file | | `0x01` | EOF | End of file |
| `0x04` | Extended Address | Sets upper 16 bits of target address | | `0x04` | Extended Address | Sets upper 16 bits of target address |
## FW02 Chunk Format (BCM4500 Firmware) ## FW02 Chunk Format (BCM4500 Firmware)
FW02 is only relevant for Rev.1 Warm devices (PID `0x0201`). It uses a custom chunk protocol: FW02 is only relevant for Rev.1 Warm devices (PID `0x0201`). It uses a custom chunk protocol:
``` ```
Chunk format: Chunk format:
Byte 0: payload_length (N) Byte 0: payload_length (N)
Bytes 1-3: header/address bytes Bytes 1-3: header/address bytes
Bytes 4..N+3: payload data Bytes 4..N+3: payload data
Terminator: single byte 0xFF Terminator: single byte 0xFF
Maximum chunk size: 64 bytes (USB control transfer limit) Maximum chunk size: 64 bytes (USB control transfer limit)
``` ```
The loading sequence: The loading sequence:
<Steps> <Steps>
1. **Initiate transfer**: Send `LOAD_BCM4500` command (`0x88`, `wValue=1`) 1. **Initiate transfer**: Send `LOAD_BCM4500` command (`0x88`, `wValue=1`)
2. **Download chunks**: Iterate through firmware data, sending each chunk via `dvb_usb_generic_write()` on bulk endpoint `0x01` 2. **Download chunks**: Iterate through firmware data, sending each chunk via `dvb_usb_generic_write()` on bulk endpoint `0x01`
3. **Detect end**: Stop when a byte with value `0xFF` is encountered 3. **Detect end**: Stop when a byte with value `0xFF` is encountered
</Steps> </Steps>
```c title="BCM4500 firmware loading (from gp8psk.c)" ```c title="BCM4500 firmware loading (from gp8psk.c)"
ptr = fw_data; ptr = fw_data;
while (ptr[0] != 0xFF) { while (ptr[0] != 0xFF) {
chunk_size = ptr[0] + 4; chunk_size = ptr[0] + 4;
if (chunk_size > 64) { if (chunk_size > 64) {
// Error: chunk too large // Error: chunk too large
} }
usb_control_msg(device, USB_SNDCTRLPIPE, 0, ..., usb_control_msg(device, USB_SNDCTRLPIPE, 0, ...,
buf, chunk_size, 2000); buf, chunk_size, 2000);
ptr += chunk_size; ptr += chunk_size;
} }
``` ```
<Aside type="note"> <Aside type="note">
On the SkyWalker-1, command `0x88` (`LOAD_BCM4500`) routes to the STALL handler in all firmware versions -- the BCM4500 firmware is burned into ROM. The kernel driver only attempts this command for Rev.1 Warm devices after checking that `bm8pskFW_Loaded` (bit 1 of `GET_8PSK_CONFIG`) is not set. On the SkyWalker-1, command `0x88` (`LOAD_BCM4500`) routes to the STALL handler in all firmware versions -- the BCM4500 firmware is burned into ROM. The kernel driver only attempts this command for Rev.1 Warm devices after checking that `bm8pskFW_Loaded` (bit 1 of `GET_8PSK_CONFIG`) is not set.
</Aside> </Aside>
## C2 EEPROM Format vs Kernel Hexline ## C2 EEPROM Format vs Kernel Hexline
The firmware as stored in the SkyWalker-1's EEPROM uses Cypress C2 format, which is structurally different from the kernel's binary hexline format. They carry identical payload data but are different containers. The firmware as stored in the SkyWalker-1's EEPROM uses Cypress C2 format, which is structurally different from the kernel's binary hexline format. They carry identical payload data but are different containers.
| Property | C2 (EEPROM) | Hexline (Kernel FW01) | | Property | C2 (EEPROM) | Hexline (Kernel FW01) |
|----------|-------------|-----------------------| |----------|-------------|-----------------------|
| Header | 8-byte C2 with VID/PID/DID | None | | Header | 8-byte C2 with VID/PID/DID | None |
| Address encoding | Big-endian 16-bit per segment | Little-endian split (lo, hi) per record | | Address encoding | Big-endian 16-bit per segment | Little-endian split (lo, hi) per record |
| Data chunking | 1023-byte segments | Typically 16-byte records | | Data chunking | 1023-byte segments | Typically 16-byte records |
| Record overhead | 4 bytes per segment | 5 bytes per record | | Record overhead | 4 bytes per segment | 5 bytes per record |
| Terminator | `0x80xx` + entry point | Type `0x01` EOF record | | Terminator | `0x80xx` + entry point | Type `0x01` EOF record |
| Entry point | Explicit in terminator | Implicit (CPUCS at `0xE600`) | | Entry point | Explicit in terminator | Implicit (CPUCS at `0xE600`) |
A C2 file can theoretically be converted to hexline format by: A C2 file can theoretically be converted to hexline format by:
1. Stripping the 8-byte C2 header 1. Stripping the 8-byte C2 header
2. Splitting each segment into 16-byte records with type `0x00` 2. Splitting each segment into 16-byte records with type `0x00`
3. Appending an EOF record (len=0, type=`0x01`) 3. Appending an EOF record (len=0, type=`0x01`)
For the v2.06 EEPROM (9,472 code bytes), this would produce approximately 12,442 bytes in hexline format. For the v2.06 EEPROM (9,472 code bytes), this would produce approximately 12,442 bytes in hexline format.
See the [Storage Formats](/firmware/storage-formats/) page for detailed C2 format documentation. See the [Storage Formats](/firmware/storage-formats/) page for detailed C2 format documentation.
## Kernel dmesg Output ## Kernel dmesg Output
When the SkyWalker-1 is connected, the kernel logs: When the SkyWalker-1 is connected, the kernel logs:
``` ```
gp8psk: FW Version = 2.06.4 (0x20604) Build 2007/07/13 gp8psk: FW Version = 2.06.4 (0x20604) Build 2007/07/13
gp8psk: usb in 149 operation failed. gp8psk: usb in 149 operation failed.
gp8psk: failed to get FPGA version gp8psk: failed to get FPGA version
gp8psk_fe: Frontend attached gp8psk_fe: Frontend attached
gp8psk: found Genpix USB device pID = 203 (hex) gp8psk: found Genpix USB device pID = 203 (hex)
``` ```
The "failed to get FPGA version" error is command `0x95` (`GET_FPGA_VERS`, decimal 149) returning an error on some units. Despite the name, there is no FPGA on the SkyWalker-1 -- this command reads a hardware platform ID from the EEPROM. The driver logs the failure but continues normally. The "failed to get FPGA version" error is command `0x95` (`GET_FPGA_VERS`, decimal 149) returning an error on some units. Despite the name, there is no FPGA on the SkyWalker-1 -- this command reads a hardware platform ID from the EEPROM. The driver logs the failure but continues normally.

View File

@ -1,210 +1,210 @@
--- ---
title: Rev.2 Firmware Analysis title: Rev.2 Firmware Analysis
description: Deep analysis of the Rev.2 v2.10.4 firmware variant with 107 functions and transitional architecture. description: Deep analysis of the Rev.2 v2.10.4 firmware variant with 107 functions and transitional architecture.
--- ---
import { Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components'; import { Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components';
The Rev.2 v2.10.4 firmware targets the Rev.2 hardware variant (PID `0x0202`) and contains **107 functions** -- the most of any firmware version. Despite this, it produces the smallest binary (8,843 bytes) due to aggressive function decomposition into small helper routines. The Rev.2 v2.10.4 firmware targets the Rev.2 hardware variant (PID `0x0202`) and contains **107 functions** -- the most of any firmware version. Despite this, it produces the smallest binary (8,843 bytes) due to aggressive function decomposition into small helper routines.
## Architectural Position ## Architectural Position
Rev.2 sits architecturally between v2.06 and v2.13: Rev.2 sits architecturally between v2.06 and v2.13:
| Aspect | v2.06 | Rev.2 v2.10 | v2.13 | | Aspect | v2.06 | Rev.2 v2.10 | v2.13 |
|--------|-------|-------------|-------| |--------|-------|-------------|-------|
| INT0 behavior | USB re-enumeration | USB re-enumeration | Demod polling | | INT0 behavior | USB re-enumeration | USB re-enumeration | Demod polling |
| Descriptor base | `0x1200` | `0x0E00` | `0x0E00` | | Descriptor base | `0x1200` | `0x0E00` | `0x0E00` |
| Stack pointer | `0x72` | `0x4F` | `0x50` | | Stack pointer | `0x72` | `0x4F` | `0x50` |
| Vendor command range | `0x80`--`0x9D` (30) | `0x80`--`0x9A` (27) | `0x80`--`0x9D` (30) | | Vendor command range | `0x80`--`0x9D` (30) | `0x80`--`0x9A` (27) | `0x80`--`0x9D` (30) |
| Demod probe at boot | No | No | Yes | | Demod probe at boot | No | No | Yes |
| Retry loops | No | No | Yes | | Retry loops | No | No | Yes |
| Function count | 61 | **107** | 82-88 | | Function count | 61 | **107** | 82-88 |
| Binary size | 9,472 bytes | **8,843 bytes** | 9,322 bytes | | Binary size | 9,472 bytes | **8,843 bytes** | 9,322 bytes |
<Aside type="note"> <Aside type="note">
The Rev.2 already adopted v2.13's descriptor base offset (`0x0E00`) and similar stack pointer pattern, but retained v2.06's INT0 USB re-enumeration behavior. It lacks v2.13's demodulator polling, retry logic, and the three additional vendor commands (`0x9B`--`0x9D` are out of range). The Rev.2 already adopted v2.13's descriptor base offset (`0x0E00`) and similar stack pointer pattern, but retained v2.06's INT0 USB re-enumeration behavior. It lacks v2.13's demodulator polling, retry logic, and the three additional vendor commands (`0x9B`--`0x9D` are out of range).
</Aside> </Aside>
## Why 107 Functions? ## Why 107 Functions?
The high function count is driven by three factors: The high function count is driven by three factors:
1. **Granular decomposition**: Rev.2 breaks large operations into many small helper functions (10-30 bytes each), where v2.06 inlines the same logic and v2.13 recombines it differently. 1. **Granular decomposition**: Rev.2 breaks large operations into many small helper functions (10-30 bytes each), where v2.06 inlines the same logic and v2.13 recombines it differently.
2. **Massive configuration dispatcher**: `FUN_CODE_0800` is 874 bytes and contains an embedded copy of the main loop, causing Ghidra to count additional entry points as separate functions. 2. **Massive configuration dispatcher**: `FUN_CODE_0800` is 874 bytes and contains an embedded copy of the main loop, causing Ghidra to count additional entry points as separate functions.
3. **Extra I2C/demodulator helper chains**: GPIO control primitives, hardware-polling wait loops, and I2C bus management exist as individual callable units rather than being inlined. 3. **Extra I2C/demodulator helper chains**: GPIO control primitives, hardware-polling wait loops, and I2C bus management exist as individual callable units rather than being inlined.
## Function Inventory Overview ## Function Inventory Overview
The 107 functions are organized into logical groups: The 107 functions are organized into logical groups:
### Vector Table and ISR Region (0x0000--0x0055) ### Vector Table and ISR Region (0x0000--0x0055)
| Address | Name | Size | Role | | Address | Name | Size | Role |
|---------|------|-----:|------| |---------|------|-----:|------|
| `0x0000` | `RESET_vector` | 3 | Jump to `main` at `0x155F` | | `0x0000` | `RESET_vector` | 3 | Jump to `main` at `0x155F` |
| `0x0003` | `INT0_ISR` | 12 | INT0 handler -- USB re-enumeration | | `0x0003` | `INT0_ISR` | 12 | INT0 handler -- USB re-enumeration |
| `0x000F` | `INT0_ISR_bit_clear` | 36 | CPUCS pulse, IRQ clear, delay | | `0x000F` | `INT0_ISR_bit_clear` | 36 | CPUCS pulse, IRQ clear, delay |
| `0x0033` | `INT2_USB_GPIF_vector` | 3 | Clears CCON.4 (PCA timer) | | `0x0033` | `INT2_USB_GPIF_vector` | 3 | Clears CCON.4 (PCA timer) |
| `0x0036` | `i2c_exchange_byte` | 5 | I2C byte exchange primitive | | `0x0036` | `i2c_exchange_byte` | 5 | I2C byte exchange primitive |
| `0x003B` | `I2C_ISR` | 8 | I2C interrupt handler | | `0x003B` | `I2C_ISR` | 8 | I2C interrupt handler |
| `0x0043` | `INT4_FX2_vector` | 8 | Sets `_0_1` flag, clears EXIF.4 | | `0x0043` | `INT4_FX2_vector` | 8 | Sets `_0_1` flag, clears EXIF.4 |
| `0x004B` | `INT5_FX2_vector` | 3 | Empty (RETI) | | `0x004B` | `INT5_FX2_vector` | 3 | Empty (RETI) |
| `0x0053` | `INT6_FX2_vector` | 3 | Sets `_0_1` flag, clears EXIF.4 | | `0x0053` | `INT6_FX2_vector` | 3 | Sets `_0_1` flag, clears EXIF.4 |
### Vendor Command Dispatch (0x0056--0x0319) ### Vendor Command Dispatch (0x0056--0x0319)
| Address | Name | Size | Role | | Address | Name | Size | Role |
|---------|------|-----:|------| |---------|------|-----:|------|
| `0x0056` | `vendor_cmd_dispatch` | 342 | Range check `0x80`--`0x9A`, jump table at `0x0076` | | `0x0056` | `vendor_cmd_dispatch` | 342 | Range check `0x80`--`0x9A`, jump table at `0x0076` |
| `0x01AC` | GET_8PSK_CONFIG handler | 361 | Reads config byte, calls LNB probe | | `0x01AC` | GET_8PSK_CONFIG handler | 361 | Reads config byte, calls LNB probe |
| `0x0315` | `vendor_cmd_stall` | 2 | Stall handler (empty RET) | | `0x0315` | `vendor_cmd_stall` | 2 | Stall handler (empty RET) |
| `0x0319` | Standard USB request handler | 869 | Switch for `bRequest` `0x00`--`0x0B` | | `0x0319` | Standard USB request handler | 869 | Switch for `bRequest` `0x00`--`0x0B` |
### Configuration and Tuning (0x0800--0x09A8) ### Configuration and Tuning (0x0800--0x09A8)
| Address | Name | Size | Role | | Address | Name | Size | Role |
|---------|------|-----:|------| |---------|------|-----:|------|
| `0x0800` | Config/tuning dispatcher | **874** | 128-entry switch on demod type, embedded main loop | | `0x0800` | Config/tuning dispatcher | **874** | 128-entry switch on demod type, embedded main loop |
| `0x09A9` | Main init + main loop | 699 | Hardware init, infinite poll loop | | `0x09A9` | Main init + main loop | 699 | Hardware init, infinite poll loop |
### BCM4500 and GPIF (0x0C64--0x0F00) ### BCM4500 and GPIF (0x0C64--0x0F00)
| Address | Name | Size | Role | | Address | Name | Size | Role |
|---------|------|-----:|------| |---------|------|-----:|------|
| `0x0C64` | BCM4500 firmware loader | 280 | I2C block transfer with address tracking | | `0x0C64` | BCM4500 firmware loader | 280 | I2C block transfer with address tracking |
| `0x0D7C` | GPIF/slave FIFO config | 128 | Enable/disable streaming mode | | `0x0D7C` | GPIF/slave FIFO config | 128 | Enable/disable streaming mode |
| `0x0F00` | I2C multi-byte read | 256 | Parameter setup for bus transfer | | `0x0F00` | I2C multi-byte read | 256 | Parameter setup for bus transfer |
### DiSEqC Implementation (0x07D1, 0x1D5E--0x1E3D) ### DiSEqC Implementation (0x07D1, 0x1D5E--0x1E3D)
| Address | Name | Size | Role | | Address | Name | Size | Role |
|---------|------|-----:|------| |---------|------|-----:|------|
| `0x07D1` | `DiSEqC byte transmit` | 45 | 8 data bits + odd parity via **P0.4** | | `0x07D1` | `DiSEqC byte transmit` | 45 | 8 data bits + odd parity via **P0.4** |
| `0x1D5E` | DiSEqC message sender | 59 | Iterates bytes, calls bit-bang per byte | | `0x1D5E` | DiSEqC message sender | 59 | Iterates bytes, calls bit-bang per byte |
| `0x1E3D` | DiSEqC byte wrapper | 54 | Sets P0.2, adds inter-byte delay | | `0x1E3D` | DiSEqC byte wrapper | 54 | Sets P0.2, adds inter-byte delay |
| `0x213C` | DiSEqC bit symbol | 22 | Carrier on/off via P0.3, data via P0.4 | | `0x213C` | DiSEqC bit symbol | 22 | Carrier on/off via P0.3, data via P0.4 |
| `0x20E2` | 22 kHz tone burst | 23 | P0.3 ON, 25 ticks, P0.3 OFF | | `0x20E2` | 22 kHz tone burst | 23 | P0.3 ON, 25 ticks, P0.3 OFF |
| `0x225F` | Timer2 tick wait | 6 | TF2 poll and clear (500 us tick) | | `0x225F` | Timer2 tick wait | 6 | TF2 poll and clear (500 us tick) |
<Aside type="note"> <Aside type="note">
Rev.2 uses **P0.4** as the DiSEqC data pin, unlike v2.06 (P0.7) and v2.13 (P0.0). The carrier pin P0.3 remains the same across all versions. This pin reassignment reflects the different PCB layout of the Rev.2 board. Rev.2 uses **P0.4** as the DiSEqC data pin, unlike v2.06 (P0.7) and v2.13 (P0.0). The carrier pin P0.3 remains the same across all versions. This pin reassignment reflects the different PCB layout of the Rev.2 board.
</Aside> </Aside>
### LNB and GPIO Control (0x1F5C--0x2038) ### LNB and GPIO Control (0x1F5C--0x2038)
| Address | Name | Size | Role | | Address | Name | Size | Role |
|---------|------|-----:|------| |---------|------|-----:|------|
| `0x1F5C` | LNB voltage I2C select | 41 | Probes I2C device `0x60` or address from `0xE0B6` | | `0x1F5C` | LNB voltage I2C select | 41 | Probes I2C device `0x60` or address from `0xE0B6` |
| `0x1FCF` | GPIO pin controller | 46 | Sets P0.6, P0.0, P3.4 based on parameter bits | | `0x1FCF` | GPIO pin controller | 46 | Sets P0.6, P0.0, P3.4 based on parameter bits |
| `0x2038` | GPIO clock strobe | 51 | Calls pin controller 3 times (setup, clock, cleanup) | | `0x2038` | GPIO clock strobe | 51 | Calls pin controller 3 times (setup, clock, cleanup) |
| `0x21B1` | LNB voltage select | 17 | Sets/clears P0.4, updates config bit 5 | | `0x21B1` | LNB voltage select | 17 | Sets/clears P0.4, updates config bit 5 |
| `0x21C2` | 22 kHz tone enable | 17 | Sets/clears P0.3, updates config bit 4 | | `0x21C2` | 22 kHz tone enable | 17 | Sets/clears P0.3, updates config bit 4 |
| `0x21D3` | DiSEqC port direction | 17 | Sets/clears P3.6, updates config bit 3 | | `0x21D3` | DiSEqC port direction | 17 | Sets/clears P3.6, updates config bit 3 |
### I2C Bus Management (0x19F4--0x1B90) ### I2C Bus Management (0x19F4--0x1B90)
Rev.2 decomposes I2C operations into particularly fine-grained functions: Rev.2 decomposes I2C operations into particularly fine-grained functions:
| Address | Name | Size | Role | | Address | Name | Size | Role |
|---------|------|-----:|------| |---------|------|-----:|------|
| `0x19F4` | I2C bus controller | 92 | Manages SDA/SCL via XRAM `0xE678` | | `0x19F4` | I2C bus controller | 92 | Manages SDA/SCL via XRAM `0xE678` |
| `0x1A50` | I2C address select + start | 83 | START condition generation | | `0x1A50` | I2C address select + start | 83 | START condition generation |
| `0x1AA3` | I2C stop + cleanup | 82 | STOP condition and bus release | | `0x1AA3` | I2C stop + cleanup | 82 | STOP condition and bus release |
| `0x1AF5` | I2C address write helper | 9 | Writes device address byte | | `0x1AF5` | I2C address write helper | 9 | Writes device address byte |
| `0x1B01` | I2C byte-level transfer | 67 | Single byte send/receive | | `0x1B01` | I2C byte-level transfer | 67 | Single byte send/receive |
| `0x1B44` | I2C ACK/NAK handling | 76 | Acknowledge detection | | `0x1B44` | I2C ACK/NAK handling | 76 | Acknowledge detection |
| `0x1B90` | I2C bus reset/recovery | 74 | Error recovery sequence | | `0x1B90` | I2C bus reset/recovery | 74 | Error recovery sequence |
| `0x1F06` | I2C completion wait | 43 | Polls XRAM `0xE678` bit 0 with 16-bit timeout | | `0x1F06` | I2C completion wait | 43 | Polls XRAM `0xE678` bit 0 with 16-bit timeout |
| `0x1F85` | I2C completion wait (2-flag) | 37 | Polls bits 0 and 2 | | `0x1F85` | I2C completion wait (2-flag) | 37 | Polls bits 0 and 2 |
| `0x2000` | I2C busy wait | 30 | Polls XRAM `0xE678` bit 6 with timeout | | `0x2000` | I2C busy wait | 30 | Polls XRAM `0xE678` bit 6 with timeout |
## Rev.2-Specific Features ## Rev.2-Specific Features
### GPIO Pin Controller (`FUN_CODE_1fcf`) ### GPIO Pin Controller (`FUN_CODE_1fcf`)
A unique function that provides parameterized GPIO control through a bit-field interface: A unique function that provides parameterized GPIO control through a bit-field interface:
```c title="GPIO pin controller (decompiled)" ```c title="GPIO pin controller (decompiled)"
void gpio_pin_controller(BYTE param) { void gpio_pin_controller(BYTE param) {
if (param & 0x02) P0 |= 0x01; // P0.0 if (param & 0x02) P0 |= 0x01; // P0.0
else P0 &= ~0x01; else P0 &= ~0x01;
if (param & 0x04) P0 |= 0x40; // P0.6 if (param & 0x04) P0 |= 0x40; // P0.6
else P0 &= ~0x40; else P0 &= ~0x40;
if (param & 0x08) P3 |= 0x10; // P3.4 if (param & 0x08) P3 |= 0x10; // P3.4
else P3 &= ~0x10; else P3 &= ~0x10;
} }
``` ```
This function is called via `FUN_CODE_2038` (GPIO clock strobe) which invokes it three times per cycle -- setup, clock edge, and cleanup -- suggesting it controls a clocked peripheral interface. This function is called via `FUN_CODE_2038` (GPIO clock strobe) which invokes it three times per cycle -- setup, clock edge, and cleanup -- suggesting it controls a clocked peripheral interface.
### Descriptor Version Checker (`FUN_CODE_1f31`) ### Descriptor Version Checker (`FUN_CODE_1f31`)
Walks a USB descriptor chain checking whether `descriptor_byte + 1 == 0x03`, enabling hardware-revision-aware code paths. This mechanism appears in a simplified form in v2.13 as the `_1_3` flag check. Walks a USB descriptor chain checking whether `descriptor_byte + 1 == 0x03`, enabling hardware-revision-aware code paths. This mechanism appears in a simplified form in v2.13 as the `_1_3` flag check.
### Prototype Commands 0x99/0x9A ### Prototype Commands 0x99/0x9A
Commands 0x99 and 0x9A exist in Rev.2 as partial prototype implementations, before becoming fully functional in v2.13: Commands 0x99 and 0x9A exist in Rev.2 as partial prototype implementations, before becoming fully functional in v2.13:
| Command | Rev.2 Behavior | v2.13 Behavior | | Command | Rev.2 Behavior | v2.13 Behavior |
|---------|---------------|---------------| |---------|---------------|---------------|
| `0x99` | Prototype -- limited status read | Full GET_DEMOD_STATUS (reads BCM4500 reg `0xF9`) | | `0x99` | Prototype -- limited status read | Full GET_DEMOD_STATUS (reads BCM4500 reg `0xF9`) |
| `0x9A` | Prototype -- basic init call | Full INIT_DEMOD (3-attempt re-init with flag check) | | `0x9A` | Prototype -- basic init call | Full INIT_DEMOD (3-attempt re-init with flag check) |
## Cross-Version Function Mapping ## Cross-Version Function Mapping
Key Rev.2 functions and their counterparts in other versions: Key Rev.2 functions and their counterparts in other versions:
| Rev.2 Function | Role | v2.06 | v2.13 | | Rev.2 Function | Role | v2.06 | v2.13 |
|----------------|------|-------|-------| |----------------|------|-------|-------|
| `0x155F` main | RESET entry, IRAM clear | `0x188D` | `0x170D` | | `0x155F` main | RESET entry, IRAM clear | `0x188D` | `0x170D` |
| `0x09A9` main init | Init + main loop | `0x09A7` | `0x0800` | | `0x09A9` main init | Init + main loop | `0x09A7` | `0x0800` |
| `0x10D9` USB setup | Descriptor/peripheral init | `0x13C3` | `0x11AB` | | `0x10D9` USB setup | Descriptor/peripheral init | `0x13C3` | `0x11AB` |
| `0x0056` vendor dispatch | Vendor command dispatcher | `0x0056` | `0x0056` | | `0x0056` vendor dispatch | Vendor command dispatcher | `0x0056` | `0x0056` |
| `0x0C64` BCM4500 loader | Firmware block transfer | `0x0DDD` | `0x0CA4` | | `0x0C64` BCM4500 loader | Firmware block transfer | `0x0DDD` | `0x0CA4` |
| `0x0D7C` GPIF/FIFO | Streaming management | `0x1919` | `0x1800` | | `0x0D7C` GPIF/FIFO | Streaming management | `0x1919` | `0x1800` |
| `0x1BDA` delay | Clock-compensated delay | `0x1DFB` | `0x14B9` | | `0x1BDA` delay | Clock-compensated delay | `0x1DFB` | `0x14B9` |
## GPIO Differences from SkyWalker-1 ## GPIO Differences from SkyWalker-1
The Rev.2 board has a different GPIO assignment from the standard SkyWalker-1: The Rev.2 board has a different GPIO assignment from the standard SkyWalker-1:
| Pin | Rev.2 v2.10 | v2.06 / v2.13 | | Pin | Rev.2 v2.10 | v2.06 / v2.13 |
|-----|-------------|---------------| |-----|-------------|---------------|
| P0.0 | LNB control (cmd `0x97`) | DiSEqC data (v2.13) / unused (v2.06) | | P0.0 | LNB control (cmd `0x97`) | DiSEqC data (v2.13) / unused (v2.06) |
| P0.4 | LNB voltage **+ DiSEqC data** | LNB voltage only | | P0.4 | LNB voltage **+ DiSEqC data** | LNB voltage only |
| P0.5 | GPIO status input (cmd `0x98`) | BCM4500 RESET | | P0.5 | GPIO status input (cmd `0x98`) | BCM4500 RESET |
| P0.6 | GPIO control (cmd `0x97`) | Unused | | P0.6 | GPIO control (cmd `0x97`) | Unused |
| P0.7 | Streaming indicator | DiSEqC data (v2.06) / streaming (v2.13) | | P0.7 | Streaming indicator | DiSEqC data (v2.06) / streaming (v2.13) |
The most significant difference is that Rev.2 multiplexes DiSEqC data onto the LNB voltage pin (P0.4), and the BCM4500 RESET function on P0.5 is replaced by a GPIO status input. The most significant difference is that Rev.2 multiplexes DiSEqC data onto the LNB voltage pin (P0.4), and the BCM4500 RESET function on P0.5 is replaced by a GPIO status input.
## Main Loop Structure ## Main Loop Structure
The Rev.2 main loop follows the same pattern as other versions but with the event handling delegated to `FUN_CODE_201e`: The Rev.2 main loop follows the same pattern as other versions but with the event handling delegated to `FUN_CODE_201e`:
```c title="Main loop poll (simplified)" ```c title="Main loop poll (simplified)"
void main_loop(void) { void main_loop(void) {
// Process init table from CODE:0B48 // Process init table from CODE:0B48
// Call USB/peripheral setup // Call USB/peripheral setup
// Enable interrupts // Enable interrupts
while (1) { while (1) {
if (sudav_flag) { if (sudav_flag) {
handle_setupdata(); handle_setupdata();
sudav_flag = 0; sudav_flag = 0;
} }
FUN_CODE_201e(); // Delegated I2C config read/write FUN_CODE_201e(); // Delegated I2C config read/write
if (gpif_flag) { if (gpif_flag) {
handle_gpif_event(); handle_gpif_event();
gpif_flag = 0; gpif_flag = 0;
} else { } else {
PCON |= 0x01; // CPU idle PCON |= 0x01; // CPU idle
} }
} }
} }
``` ```

View File

@ -1,256 +1,256 @@
--- ---
title: Firmware Storage Formats title: Firmware Storage Formats
description: Cypress C2 EEPROM boot format, kernel hexline format, and flat binary extraction. description: Cypress C2 EEPROM boot format, kernel hexline format, and flat binary extraction.
--- ---
import { Tabs, TabItem, Aside, FileTree, Badge } from '@astrojs/starlight/components'; import { Tabs, TabItem, Aside, FileTree, Badge } from '@astrojs/starlight/components';
The SkyWalker-1 firmware exists in multiple container formats depending on context: the onboard EEPROM uses the Cypress C2 IIC boot format, the Linux kernel expects a custom binary hexline format, and analysis tools work with flat extracted binaries. The SkyWalker-1 firmware exists in multiple container formats depending on context: the onboard EEPROM uses the Cypress C2 IIC boot format, the Linux kernel expects a custom binary hexline format, and analysis tools work with flat extracted binaries.
## Format Overview ## Format Overview
<Tabs> <Tabs>
<TabItem label="C2 EEPROM"> <TabItem label="C2 EEPROM">
### Cypress C2 IIC Second-Stage Boot Format <Badge text="Device Storage" variant="note" /> ### Cypress C2 IIC Second-Stage Boot Format <Badge text="Device Storage" variant="note" />
This is the native format stored in the SkyWalker-1's onboard I2C EEPROM. The FX2's internal boot ROM reads this format on power-up. This is the native format stored in the SkyWalker-1's onboard I2C EEPROM. The FX2's internal boot ROM reads this format on power-up.
The `0xC2` marker byte in the header identifies this as "external memory, large code model" -- it tells the boot ROM to load code from the EEPROM into internal RAM using the segment map that follows. The `0xC2` marker byte in the header identifies this as "external memory, large code model" -- it tells the boot ROM to load code from the EEPROM into internal RAM using the segment map that follows.
</TabItem> </TabItem>
<TabItem label="Hexline"> <TabItem label="Hexline">
### Kernel Binary Hexline Format <Badge text="Linux Driver" variant="caution" /> ### Kernel Binary Hexline Format <Badge text="Linux Driver" variant="caution" />
Used only by `dvb-usb-gp8psk-01.fw` for Rev.1 Cold devices. This is a compact binary representation of Intel HEX records parsed by `dvb_usb_get_hexline()` in the kernel. It is NOT standard Intel HEX text. Used only by `dvb-usb-gp8psk-01.fw` for Rev.1 Cold devices. This is a compact binary representation of Intel HEX records parsed by `dvb_usb_get_hexline()` in the kernel. It is NOT standard Intel HEX text.
</TabItem> </TabItem>
<TabItem label="Flat Binary"> <TabItem label="Flat Binary">
### Flat Extracted Binary <Badge text="Analysis" variant="success" /> ### Flat Extracted Binary <Badge text="Analysis" variant="success" />
Raw 8051 machine code extracted from C2 segments. No headers or framing -- just code bytes at their target RAM addresses. Used for Ghidra analysis and binary diffing. Raw 8051 machine code extracted from C2 segments. No headers or framing -- just code bytes at their target RAM addresses. Used for Ghidra analysis and binary diffing.
</TabItem> </TabItem>
</Tabs> </Tabs>
## C2 EEPROM Format ## C2 EEPROM Format
### Header Structure (8 bytes) ### Header Structure (8 bytes)
``` ```
Offset Size Field Value (SkyWalker-1) Offset Size Field Value (SkyWalker-1)
------ ---- ---------- ------------------- ------ ---- ---------- -------------------
0x00 1 marker 0xC2 (external memory, large code model) 0x00 1 marker 0xC2 (external memory, large code model)
0x01 2 VID 0xC009 -> 0x09C0 (little-endian, Genpix) 0x01 2 VID 0xC009 -> 0x09C0 (little-endian, Genpix)
0x03 2 PID 0x0302 -> 0x0203 (little-endian, SkyWalker-1) 0x03 2 PID 0x0302 -> 0x0203 (little-endian, SkyWalker-1)
0x05 2 DID 0x0000 (device ID, unused) 0x05 2 DID 0x0000 (device ID, unused)
0x07 1 config 0x40 (400 kHz I2C bus speed) 0x07 1 config 0x40 (400 kHz I2C bus speed)
``` ```
The VID and PID in the C2 header determine the USB identifiers that the FX2 enumerates with after boot. This is how the kernel driver identifies the device model. The VID and PID in the C2 header determine the USB identifiers that the FX2 enumerates with after boot. This is how the kernel driver identifies the device model.
### Config Byte (offset 0x07) ### Config Byte (offset 0x07)
| Value | I2C Speed | Notes | | Value | I2C Speed | Notes |
|-------|-----------|-------| |-------|-----------|-------|
| `0x00` | 100 kHz | Default if EEPROM missing | | `0x00` | 100 kHz | Default if EEPROM missing |
| `0x20` | 200 kHz | | | `0x20` | 200 kHz | |
| `0x40` | **400 kHz** | Used by SkyWalker-1 | | `0x40` | **400 kHz** | Used by SkyWalker-1 |
### Code Segment Structure ### Code Segment Structure
Following the 8-byte header, one or more code segments: Following the 8-byte header, one or more code segments:
``` ```
Offset Size Field Offset Size Field
------ ---------- ----- ------ ---------- -----
0 2 seg_len (big-endian) -- number of data bytes 0 2 seg_len (big-endian) -- number of data bytes
2 2 seg_addr (big-endian) -- target RAM address 2 2 seg_addr (big-endian) -- target RAM address
4 seg_len data[] -- code/data bytes 4 seg_len data[] -- code/data bytes
``` ```
Segments are packed contiguously. The 1023-byte maximum segment size is the limit of the FX2 boot ROM's internal I2C read buffer. Segments are packed contiguously. The 1023-byte maximum segment size is the limit of the FX2 boot ROM's internal I2C read buffer.
### Terminator ### Terminator
``` ```
Offset Size Field Offset Size Field
------ ---- ----- ------ ---- -----
0 2 0x8001 -- high bit set signals terminator (length with MSB set) 0 2 0x8001 -- high bit set signals terminator (length with MSB set)
2 2 entry -- entry point address (big-endian) = 0xE600 (CPUCS) 2 2 entry -- entry point address (big-endian) = 0xE600 (CPUCS)
``` ```
Writing to CPUCS (`0xE600`) with value `0x00` releases the CPU from reset and begins execution at the reset vector (`0x0000`). Writing to CPUCS (`0xE600`) with value `0x00` releases the CPU from reset and begins execution at the reset vector (`0x0000`).
## Decoded C2 Files ## Decoded C2 Files
### Header Comparison ### Header Comparison
| File | VID | PID | DID | I2C Speed | Code Size | | File | VID | PID | DID | I2C Speed | Code Size |
|------|-----|-----|-----|-----------|-----------| |------|-----|-----|-----|-----------|-----------|
| `skywalker1_eeprom.bin` (v2.06) | `0x09C0` | **`0x0203`** | `0x0000` | 400 kHz | 9,472 bytes | | `skywalker1_eeprom.bin` (v2.06) | `0x09C0` | **`0x0203`** | `0x0000` | 400 kHz | 9,472 bytes |
| `sw1_v213_fw_1_c2.bin` (v2.13.1) | `0x09C0` | **`0x0203`** | `0x0000` | 400 kHz | 9,322 bytes | | `sw1_v213_fw_1_c2.bin` (v2.13.1) | `0x09C0` | **`0x0203`** | `0x0000` | 400 kHz | 9,322 bytes |
| `sw1_v213_fw_2_c2.bin` (v2.13.2) | `0x09C0` | **`0x0203`** | `0x0000` | 400 kHz | 9,377 bytes | | `sw1_v213_fw_2_c2.bin` (v2.13.2) | `0x09C0` | **`0x0203`** | `0x0000` | 400 kHz | 9,377 bytes |
| `sw1_v213_fw_3_c2.bin` (v2.13.3) | `0x09C0` | **`0x0203`** | `0x0000` | 400 kHz | 9,369 bytes | | `sw1_v213_fw_3_c2.bin` (v2.13.3) | `0x09C0` | **`0x0203`** | `0x0000` | 400 kHz | 9,369 bytes |
| `rev2_v210_fw_1_c2.bin` (Rev.2) | `0x09C0` | **`0x0202`** | `0x0000` | 400 kHz | 8,843 bytes | | `rev2_v210_fw_1_c2.bin` (Rev.2) | `0x09C0` | **`0x0202`** | `0x0000` | 400 kHz | 8,843 bytes |
<Aside type="note"> <Aside type="note">
Rev.2 uses PID `0x0202` while all SkyWalker-1 variants use `0x0203`. This PID difference is the primary mechanism by which the kernel driver distinguishes hardware revisions. The DID field is unused (always `0x0000`). Rev.2 uses PID `0x0202` while all SkyWalker-1 variants use `0x0203`. This PID difference is the primary mechanism by which the kernel driver distinguishes hardware revisions. The DID field is unused (always `0x0000`).
</Aside> </Aside>
### Segment Layout (SkyWalker-1 Variants) ### Segment Layout (SkyWalker-1 Variants)
All SkyWalker-1 C2 files use uniform 1023-byte segments (except the last): All SkyWalker-1 C2 files use uniform 1023-byte segments (except the last):
| Segment | Address | Length | Notes | | Segment | Address | Length | Notes |
|---------|---------|-------:|-------| |---------|---------|-------:|-------|
| 1 | `0x0000` | 1023 | Reset vector, interrupt handlers | | 1 | `0x0000` | 1023 | Reset vector, interrupt handlers |
| 2 | `0x03FF` | 1023 | | | 2 | `0x03FF` | 1023 | |
| 3 | `0x07FE` | 1023 | | | 3 | `0x07FE` | 1023 | |
| 4 | `0x0BFD` | 1023 | | | 4 | `0x0BFD` | 1023 | |
| 5 | `0x0FFC` | 1023 | | | 5 | `0x0FFC` | 1023 | |
| 6 | `0x13FB` | 1023 | | | 6 | `0x13FB` | 1023 | |
| 7 | `0x17FA` | 1023 | | | 7 | `0x17FA` | 1023 | |
| 8 | `0x1BF9` | 1023 | | | 8 | `0x1BF9` | 1023 | |
| 9 | `0x1FF8` | 1023 | | | 9 | `0x1FF8` | 1023 | |
| 10 | `0x23F7` | varies | 115--265 bytes depending on version | | 10 | `0x23F7` | varies | 115--265 bytes depending on version |
The address of each segment is exactly `previous_addr + 1023`, creating a contiguous mapping from `0x0000` to the end of the firmware image. The address of each segment is exactly `previous_addr + 1023`, creating a contiguous mapping from `0x0000` to the end of the firmware image.
### Rev.2 Segment Layout ### Rev.2 Segment Layout
Rev.2 has only 9 segments (one fewer than SkyWalker-1 variants) because its firmware is smaller: Rev.2 has only 9 segments (one fewer than SkyWalker-1 variants) because its firmware is smaller:
| Segment | Address | Length | | Segment | Address | Length |
|---------|---------|-------:| |---------|---------|-------:|
| 1 | `0x0000` | 1023 | | 1 | `0x0000` | 1023 |
| 2 | `0x03FF` | 1023 | | 2 | `0x03FF` | 1023 |
| 3 | `0x07FE` | 1023 | | 3 | `0x07FE` | 1023 |
| 4 | `0x0BFD` | 1023 | | 4 | `0x0BFD` | 1023 |
| 5 | `0x0FFC` | 1023 | | 5 | `0x0FFC` | 1023 |
| 6 | `0x13FB` | 1023 | | 6 | `0x13FB` | 1023 |
| 7 | `0x17FA` | 1023 | | 7 | `0x17FA` | 1023 |
| 8 | `0x1BF9` | 1023 | | 8 | `0x1BF9` | 1023 |
| 9 | `0x1FF8` | 659 | | 9 | `0x1FF8` | 659 |
## Kernel Binary Hexline Format ## Kernel Binary Hexline Format
This format is used exclusively by `dvb-usb-gp8psk-01.fw` for loading firmware into Rev.1 Cold devices (PID `0x0200`). The SkyWalker-1 never uses this format at runtime. This format is used exclusively by `dvb-usb-gp8psk-01.fw` for loading firmware into Rev.1 Cold devices (PID `0x0200`). The SkyWalker-1 never uses this format at runtime.
### Record Structure ### Record Structure
``` ```
Offset Size Field Offset Size Field
------ ---- ----- ------ ---- -----
0 1 len Number of data bytes in this record 0 1 len Number of data bytes in this record
1 1 addr_lo Target address, low byte 1 1 addr_lo Target address, low byte
2 1 addr_hi Target address, high byte 2 1 addr_hi Target address, high byte
3 1 type Record type 3 1 type Record type
4 len data[] Payload bytes 4 len data[] Payload bytes
4+len 1 chk Checksum byte 4+len 1 chk Checksum byte
Total per record: len + 5 bytes Total per record: len + 5 bytes
``` ```
### Record Types ### Record Types
| Type | Name | Purpose | | Type | Name | Purpose |
|------|------|---------| |------|------|---------|
| `0x00` | Data | Write data bytes to FX2 RAM at address `(addr_hi * 256 + addr_lo)` | | `0x00` | Data | Write data bytes to FX2 RAM at address `(addr_hi * 256 + addr_lo)` |
| `0x01` | EOF | End of file, no more records | | `0x01` | EOF | End of file, no more records |
| `0x04` | Extended Linear Address | `data[0]:data[1]` = upper 16 bits of target address | | `0x04` | Extended Linear Address | `data[0]:data[1]` = upper 16 bits of target address |
### Comparison With Other DVB-USB Firmware ### Comparison With Other DVB-USB Firmware
Files from other DVB-USB devices confirm the format: Files from other DVB-USB devices confirm the format:
| File | Size | First Record | | File | Size | First Record |
|------|-----:|-------------| |------|-----:|-------------|
| `dvb-usb-dib0700-1.20.fw` | 33,768 | len=2, addr=0x0000, type=0x04 | | `dvb-usb-dib0700-1.20.fw` | 33,768 | len=2, addr=0x0000, type=0x04 |
| `dvb-usb-it9135-01.fw` | 8,128 | len=3, addr=0x0000, type=0x03 | | `dvb-usb-it9135-01.fw` | 8,128 | len=3, addr=0x0000, type=0x03 |
| `dvb-usb-it9135-02.fw` | 5,834 | len=3, addr=0x0000, type=0x03 | | `dvb-usb-it9135-02.fw` | 5,834 | len=3, addr=0x0000, type=0x03 |
## 64K Full EEPROM Dump ## 64K Full EEPROM Dump
The complete EEPROM can be dumped as a 65,536-byte raw image. The firmware occupies the first ~10 KB; the remainder contains: The complete EEPROM can be dumped as a 65,536-byte raw image. The firmware occupies the first ~10 KB; the remainder contains:
| Offset Range | Content | | Offset Range | Content |
|-------------|---------| |-------------|---------|
| `0x0000`--`0x0007` | C2 header (8 bytes) | | `0x0000`--`0x0007` | C2 header (8 bytes) |
| `0x0008`--`0x25xx` | Code segments (varies by version) | | `0x0008`--`0x25xx` | Code segments (varies by version) |
| `0x25xx`--`0x26xx` | C2 terminator | | `0x25xx`--`0x26xx` | C2 terminator |
| `0x2700`--`0x3FFF` | Padding / unused (typically `0xFF`) | | `0x2700`--`0x3FFF` | Padding / unused (typically `0xFF`) |
| `0x4000`--`0x7FFF` | Mirror/unused (some EEPROMs wrap at 32K) | | `0x4000`--`0x7FFF` | Mirror/unused (some EEPROMs wrap at 32K) |
<Aside type="caution"> <Aside type="caution">
Not all 64K images are identical even for the same firmware version. The "unused" region after the terminator may contain artifacts from previous firmware flashes or EEPROM test patterns. Only the data from the C2 header through the terminator is meaningful. Not all 64K images are identical even for the same firmware version. The "unused" region after the terminator may contain artifacts from previous firmware flashes or EEPROM test patterns. Only the data from the C2 header through the terminator is meaningful.
</Aside> </Aside>
## Format Conversion ## Format Conversion
### C2 to Flat Binary ### C2 to Flat Binary
Extract raw code from a C2 file by stripping headers: Extract raw code from a C2 file by stripping headers:
```python title="C2 to flat binary extraction" ```python title="C2 to flat binary extraction"
def c2_to_flat(c2_data): def c2_to_flat(c2_data):
"""Extract flat binary from C2 EEPROM format.""" """Extract flat binary from C2 EEPROM format."""
pos = 8 # Skip 8-byte C2 header pos = 8 # Skip 8-byte C2 header
flat = bytearray(0x10000) # 64K address space flat = bytearray(0x10000) # 64K address space
while pos < len(c2_data): while pos < len(c2_data):
seg_len = (c2_data[pos] << 8) | c2_data[pos + 1] seg_len = (c2_data[pos] << 8) | c2_data[pos + 1]
seg_addr = (c2_data[pos + 2] << 8) | c2_data[pos + 3] seg_addr = (c2_data[pos + 2] << 8) | c2_data[pos + 3]
pos += 4 pos += 4
if seg_len & 0x8000: # Terminator (high bit set) if seg_len & 0x8000: # Terminator (high bit set)
break break
flat[seg_addr:seg_addr + seg_len] = c2_data[pos:pos + seg_len] flat[seg_addr:seg_addr + seg_len] = c2_data[pos:pos + seg_len]
pos += seg_len pos += seg_len
return flat return flat
``` ```
### C2 to Kernel Hexline ### C2 to Kernel Hexline
Theoretical conversion for producing a `dvb-usb-gp8psk-01.fw` equivalent: Theoretical conversion for producing a `dvb-usb-gp8psk-01.fw` equivalent:
```python title="C2 to kernel hexline conversion" ```python title="C2 to kernel hexline conversion"
def c2_to_hexline(c2_data): def c2_to_hexline(c2_data):
"""Convert C2 EEPROM format to kernel binary hexline.""" """Convert C2 EEPROM format to kernel binary hexline."""
records = bytearray() records = bytearray()
flat = c2_to_flat(c2_data) flat = c2_to_flat(c2_data)
code_end = find_code_end(flat) code_end = find_code_end(flat)
for addr in range(0, code_end, 16): for addr in range(0, code_end, 16):
chunk = flat[addr:addr + 16] chunk = flat[addr:addr + 16]
rec_len = len(chunk) rec_len = len(chunk)
addr_lo = addr & 0xFF addr_lo = addr & 0xFF
addr_hi = (addr >> 8) & 0xFF addr_hi = (addr >> 8) & 0xFF
rec_type = 0x00 # Data record rec_type = 0x00 # Data record
chk = (rec_len + addr_lo + addr_hi + rec_type chk = (rec_len + addr_lo + addr_hi + rec_type
+ sum(chunk)) & 0xFF + sum(chunk)) & 0xFF
records.extend([rec_len, addr_lo, addr_hi, rec_type]) records.extend([rec_len, addr_lo, addr_hi, rec_type])
records.extend(chunk) records.extend(chunk)
records.append((~chk + 1) & 0xFF) records.append((~chk + 1) & 0xFF)
# EOF record # EOF record
records.extend([0x00, 0x00, 0x00, 0x01, 0xFF]) records.extend([0x00, 0x00, 0x00, 0x01, 0xFF])
return records return records
``` ```
For the v2.06 firmware (9,472 code bytes), this produces approximately 12,442 bytes in hexline format. For the v2.06 firmware (9,472 code bytes), this produces approximately 12,442 bytes in hexline format.
## File Identification ## File Identification
Quick format identification by examining the first byte: Quick format identification by examining the first byte:
| First Byte | Format | Notes | | First Byte | Format | Notes |
|------------|--------|-------| |------------|--------|-------|
| `0xC2` | C2 EEPROM | Standard SkyWalker-1 EEPROM dump | | `0xC2` | C2 EEPROM | Standard SkyWalker-1 EEPROM dump |
| `0xC0` | C0 EEPROM | VID/PID-only header (no code segments) | | `0xC0` | C0 EEPROM | VID/PID-only header (no code segments) |
| `0x02` | Flat binary | Likely starts with `LJMP` instruction (`0x02 xx xx`) | | `0x02` | Flat binary | Likely starts with `LJMP` instruction (`0x02 xx xx`) |
| Other | Hexline or unknown | Check record structure | | Other | Hexline or unknown | Check record structure |

View File

@ -1,330 +1,330 @@
--- ---
title: Firmware Version Comparison title: Firmware Version Comparison
description: Side-by-side comparison of all known SkyWalker-1 firmware revisions including stock and custom builds. description: Side-by-side comparison of all known SkyWalker-1 firmware revisions including stock and custom builds.
--- ---
import { Tabs, TabItem, Badge, Aside } from '@astrojs/starlight/components'; import { Tabs, TabItem, Badge, Aside } from '@astrojs/starlight/components';
Six firmware versions have been analyzed through Ghidra reverse engineering and source code review. This page compares their architecture, features, and binary characteristics. Six firmware versions have been analyzed through Ghidra reverse engineering and source code review. This page compares their architecture, features, and binary characteristics.
## Version Summary ## Version Summary
| Firmware | Version ID | Build Date | Target PID | Functions | Binary Size | Stack Pointer | | Firmware | Version ID | Build Date | Target PID | Functions | Binary Size | Stack Pointer |
|----------|-----------|------------|------------|-----------|-------------|---------------| |----------|-----------|------------|------------|-----------|-------------|---------------|
| Custom v3.05.0 | `0x030500` | 2026-02-16 | `0x0203` | N/A | 13,079 bytes (RAM) | `0x7B` | | Custom v3.05.0 | `0x030500` | 2026-02-16 | `0x0203` | N/A | 13,079 bytes (RAM) | `0x7B` |
| Custom v3.01.0 | `0x030100` | 2026-02-12 | `0x0203` | N/A | ~3 KB (RAM) | N/A | | Custom v3.01.0 | `0x030100` | 2026-02-12 | `0x0203` | N/A | ~3 KB (RAM) | N/A |
| v2.13.01 (FW1) | `0x020D01` | 2010-03-12 | `0x0203` | 82-88 | 9,322 bytes | `0x50` | | v2.13.01 (FW1) | `0x020D01` | 2010-03-12 | `0x0203` | 82-88 | 9,322 bytes | `0x50` |
| v2.13.02 (FW2) | `0x020D01` | 2010-03-12 | `0x0203` | 83 | 9,377 bytes | `0x50` | | v2.13.02 (FW2) | `0x020D01` | 2010-03-12 | `0x0203` | 83 | 9,377 bytes | `0x50` |
| v2.13.03 (FW3) | `0x020D01` | 2010-03-12 | `0x0203` | 83 | 9,369 bytes | `0x52` | | v2.13.03 (FW3) | `0x020D01` | 2010-03-12 | `0x0203` | 83 | 9,369 bytes | `0x52` |
| Rev.2 v2.10.04 | `0x020A04` | 2010-03-12 | `0x0202` | 107 | 8,843 bytes | `0x4F` | | Rev.2 v2.10.04 | `0x020A04` | 2010-03-12 | `0x0202` | 107 | 8,843 bytes | `0x4F` |
| v2.06.04 | `0x020604` | 2007-07-13 | `0x0203` | 61 | 9,472 bytes | `0x72` | | v2.06.04 | `0x020604` | 2007-07-13 | `0x0203` | 61 | 9,472 bytes | `0x72` |
<Aside type="note"> <Aside type="note">
Rev.2 v2.10 targets PID `0x0202` (a different product line). All other versions target `0x0203` (SkyWalker-1). The custom firmware versions are compiled with SDCC + fx2lib and loaded into FX2 RAM, not flashed to EEPROM. Custom v3.05.0 is the safety-hardened release with software watchdog and comprehensive timeout protection. Rev.2 v2.10 targets PID `0x0202` (a different product line). All other versions target `0x0203` (SkyWalker-1). The custom firmware versions are compiled with SDCC + fx2lib and loaded into FX2 RAM, not flashed to EEPROM. Custom v3.05.0 is the safety-hardened release with software watchdog and comprehensive timeout protection.
</Aside> </Aside>
## Version-by-Version Details ## Version-by-Version Details
<Tabs> <Tabs>
<TabItem label="Custom v3.05"> <TabItem label="Custom v3.05">
### Custom v3.05.0 <Badge text="Custom" variant="success" /> <Badge text="Safety" variant="caution" /> ### Custom v3.05.0 <Badge text="Custom" variant="success" /> <Badge text="Safety" variant="caution" />
Safety-hardened firmware with software watchdog and timeout protection on all code paths. Built on the v3.04 codebase with all features from v3.01 through v3.04. Safety-hardened firmware with software watchdog and timeout protection on all code paths. Built on the v3.04 codebase with all features from v3.01 through v3.04.
| Property | Value | | Property | Value |
|----------|-------| |----------|-------|
| Version ID | `0x030500` | | Version ID | `0x030500` |
| Build date | 2026-02-16 | | Build date | 2026-02-16 |
| Toolchain | SDCC + fx2lib | | Toolchain | SDCC + fx2lib |
| Source | `firmware/skywalker1.c` (2,256 lines) | | Source | `firmware/skywalker1.c` (2,256 lines) |
| Code size | 13,079 / 15,360 bytes (85%) | | Code size | 13,079 / 15,360 bytes (85%) |
| XRAM | 218 / 512 bytes (43%) | | XRAM | 218 / 512 bytes (43%) |
| Stack | 132 bytes available | | Stack | 132 bytes available |
| Error codes | 14 (`0x00`--`0x0D`) | | Error codes | 14 (`0x00`--`0x0D`) |
**Additions over v3.04:** **Additions over v3.04:**
- Timer0 software watchdog (2-second window, cuts LNB power on stall) - Timer0 software watchdog (2-second window, cuts LNB power on stall)
- Timeout protection on all EP0, GPIF, EP2, and DiSEqC Timer2 spin loops - Timeout protection on all EP0, GPIF, EP2, and DiSEqC Timer2 spin loops
- `ep0_wait_data()` helper replacing 7 bare `while (EP0CS & bmEPBUSY)` loops - `ep0_wait_data()` helper replacing 7 bare `while (EP0CS & bmEPBUSY)` loops
- EP0 payload length validation on all OUT vendor commands - EP0 payload length validation on all OUT vendor commands
- I2C return-value checks on all write operations in sweep/scan functions - I2C return-value checks on all write operations in sweep/scan functions
- `do_tune()` rewritten with timeout-protected I2C and early guard for unbooted BCM4500 - `do_tune()` rewritten with timeout-protected I2C and early guard for unbooted BCM4500
- 8 new error codes for observable failure modes - 8 new error codes for observable failure modes
- 55-test Hamilton adversarial test suite (`test_hamilton.py`) - 55-test Hamilton adversarial test suite (`test_hamilton.py`)
See the [Custom v3.05](/firmware/custom-v305/) page for the full safety review findings and hardware validation results. See the [Custom v3.05](/firmware/custom-v305/) page for the full safety review findings and hardware validation results.
</TabItem> </TabItem>
<TabItem label="Custom v3.01"> <TabItem label="Custom v3.01">
### Custom v3.01.0 <Badge text="Custom" variant="success" /> ### Custom v3.01.0 <Badge text="Custom" variant="success" />
Open-source replacement firmware built with SDCC + fx2lib. RAM-loaded for testing. Open-source replacement firmware built with SDCC + fx2lib. RAM-loaded for testing.
| Property | Value | | Property | Value |
|----------|-------| |----------|-------|
| Version ID | `0x030100` | | Version ID | `0x030100` |
| Build date | 2026-02-12 | | Build date | 2026-02-12 |
| Toolchain | SDCC + fx2lib | | Toolchain | SDCC + fx2lib |
| Source | `firmware/skywalker1.c` (1351 lines) | | Source | `firmware/skywalker1.c` (1351 lines) |
| Binary size | ~3 KB | | Binary size | ~3 KB |
| Load method | RAM upload via `tools/fw_load.py` | | Load method | RAM upload via `tools/fw_load.py` |
| DiSEqC data pin | P0.7 (v2.06 assignment) | | DiSEqC data pin | P0.7 (v2.06 assignment) |
**Additions over stock:** **Additions over stock:**
- Seven new diagnostic commands (`0xB0`--`0xB6`) - Seven new diagnostic commands (`0xB0`--`0xB6`)
- Incremental debug boot modes (wValue `0x80`--`0x85` for BOOT_8PSK) - Incremental debug boot modes (wValue `0x80`--`0x85` for BOOT_8PSK)
- I2C timeout protection (6000-iteration countdown vs. infinite spin) - I2C timeout protection (6000-iteration countdown vs. infinite spin)
- I2C bus scan for device discovery - I2C bus scan for device discovery
- Spectrum sweep and blind scan capabilities - Spectrum sweep and blind scan capabilities
- Raw BCM4500 register access - Raw BCM4500 register access
See the [Custom v3.01](/firmware/custom-v301/) page for full details. See the [Custom v3.01](/firmware/custom-v301/) page for full details.
</TabItem> </TabItem>
<TabItem label="v2.13 FW1"> <TabItem label="v2.13 FW1">
### v2.13.01 (FW1) <Badge text="Stock" variant="note" /> ### v2.13.01 (FW1) <Badge text="Stock" variant="note" />
The most feature-complete stock firmware, targeting the original I2C-connected SkyWalker-1 hardware. The most feature-complete stock firmware, targeting the original I2C-connected SkyWalker-1 hardware.
| Property | Value | | Property | Value |
|----------|-------| |----------|-------|
| Version ID | `0x020D01` | | Version ID | `0x020D01` |
| Build date | 2010-03-12 | | Build date | 2010-03-12 |
| Functions | 82-88 | | Functions | 82-88 |
| Binary size | 9,322 bytes | | Binary size | 9,322 bytes |
| Stack pointer | `0x50` | | Stack pointer | `0x50` |
| Config byte IRAM | `0x4F` | | Config byte IRAM | `0x4F` |
| Descriptor base | `0x0E00` | | Descriptor base | `0x0E00` |
| Init table address | `CODE:0B88` | | Init table address | `CODE:0B88` |
| Vendor commands | 30 (`0x80`--`0x9D`) | | Vendor commands | 30 (`0x80`--`0x9D`) |
| DiSEqC data pin | P0.0 | | DiSEqC data pin | P0.0 |
**New features over v2.06:** **New features over v2.06:**
- Three new vendor commands: `0x99` (GET_DEMOD_STATUS), `0x9A` (INIT_DEMOD), `0x9C` (DELAY_COMMAND) - Three new vendor commands: `0x99` (GET_DEMOD_STATUS), `0x9A` (INIT_DEMOD), `0x9C` (DELAY_COMMAND)
- INT0 repurposed for demodulator availability polling (40 attempts at addresses 0x7F and 0x3F) - INT0 repurposed for demodulator availability polling (40 attempts at addresses 0x7F and 0x3F)
- USB re-enumeration moved to `FUN_CODE_2031` (called as normal function before main loop) - USB re-enumeration moved to `FUN_CODE_2031` (called as normal function before main loop)
- Demodulator signature verification (`FUN_CODE_1799`) with 20 retry attempts - Demodulator signature verification (`FUN_CODE_1799`) with 20 retry attempts
- Descriptor checksum verification (`FUN_CODE_1ca0`) with 20 retry attempts - Descriptor checksum verification (`FUN_CODE_1ca0`) with 20 retry attempts
- Hardware revision detection via descriptor byte (flag `_1_3`) - Hardware revision detection via descriptor byte (flag `_1_3`)
- Consolidated BCM4500 status polling (1 register instead of 3) - Consolidated BCM4500 status polling (1 register instead of 3)
- Anti-tampering string at firmware offset 0x1880 - Anti-tampering string at firmware offset 0x1880
See the [FW2.13 Variants](/firmware/fw213-variants/) page for sub-variant comparison. See the [FW2.13 Variants](/firmware/fw213-variants/) page for sub-variant comparison.
</TabItem> </TabItem>
<TabItem label="Rev.2 v2.10"> <TabItem label="Rev.2 v2.10">
### Rev.2 v2.10.04 <Badge text="Transitional" variant="caution" /> ### Rev.2 v2.10.04 <Badge text="Transitional" variant="caution" />
Firmware for the Rev.2 hardware variant (PID `0x0202`). Architecturally sits between v2.06 and v2.13. Firmware for the Rev.2 hardware variant (PID `0x0202`). Architecturally sits between v2.06 and v2.13.
| Property | Value | | Property | Value |
|----------|-------| |----------|-------|
| Version ID | `0x020A04` | | Version ID | `0x020A04` |
| Build date | 2010-03-12 | | Build date | 2010-03-12 |
| Functions | 107 (most of any version) | | Functions | 107 (most of any version) |
| Binary size | 8,843 bytes (smallest) | | Binary size | 8,843 bytes (smallest) |
| Stack pointer | `0x4F` | | Stack pointer | `0x4F` |
| Config byte IRAM | `0x4E` | | Config byte IRAM | `0x4E` |
| Descriptor base | `0x0E00` | | Descriptor base | `0x0E00` |
| Init table address | `CODE:0B48` | | Init table address | `CODE:0B48` |
| Vendor commands | 27 (`0x80`--`0x9A`) | | Vendor commands | 27 (`0x80`--`0x9A`) |
| DiSEqC data pin | P0.4 | | DiSEqC data pin | P0.4 |
**Characteristics:** **Characteristics:**
- Highest function count due to granular decomposition (10-30 byte helper functions) - Highest function count due to granular decomposition (10-30 byte helper functions)
- Smallest binary despite having the most functions - Smallest binary despite having the most functions
- Retained v2.06's INT0 USB re-enumeration behavior - Retained v2.06's INT0 USB re-enumeration behavior
- Already adopted v2.13's descriptor base (`0x0E00`) and similar stack pointer - Already adopted v2.13's descriptor base (`0x0E00`) and similar stack pointer
- Contains `FUN_CODE_0800`: a massive 874-byte configuration dispatcher with embedded main loop - Contains `FUN_CODE_0800`: a massive 874-byte configuration dispatcher with embedded main loop
- Lacks v2.13's demodulator polling, retry loops, and additional vendor commands (0x9B--0x9D out of range) - Lacks v2.13's demodulator polling, retry loops, and additional vendor commands (0x9B--0x9D out of range)
- 0x99/0x9A present as prototype implementations - 0x99/0x9A present as prototype implementations
See the [Rev.2 Analysis](/firmware/rev2-analysis/) page for the complete 107-function inventory. See the [Rev.2 Analysis](/firmware/rev2-analysis/) page for the complete 107-function inventory.
</TabItem> </TabItem>
<TabItem label="v2.06"> <TabItem label="v2.06">
### v2.06.04 <Badge text="Stock" variant="note" /> ### v2.06.04 <Badge text="Stock" variant="note" />
The original SkyWalker-1 firmware extracted from the device's onboard EEPROM. The original SkyWalker-1 firmware extracted from the device's onboard EEPROM.
| Property | Value | | Property | Value |
|----------|-------| |----------|-------|
| Version ID | `0x020604` | | Version ID | `0x020604` |
| Build date | 2007-07-13 | | Build date | 2007-07-13 |
| Functions | 61 | | Functions | 61 |
| Binary size | 9,472 bytes | | Binary size | 9,472 bytes |
| Stack pointer | `0x72` | | Stack pointer | `0x72` |
| Config byte IRAM | `0x6D` | | Config byte IRAM | `0x6D` |
| Descriptor base | `0x1200` | | Descriptor base | `0x1200` |
| Init table address | `CODE:0B46` | | Init table address | `CODE:0B46` |
| Vendor commands | 30 (`0x80`--`0x9D`) | | Vendor commands | 30 (`0x80`--`0x9D`) |
| DiSEqC data pin | P0.7 | | DiSEqC data pin | P0.7 |
**Characteristics:** **Characteristics:**
- Simplest firmware with the fewest functions - Simplest firmware with the fewest functions
- INT0 handler performs USB re-enumeration (CPUCS pulse) - INT0 handler performs USB re-enumeration (CPUCS pulse)
- No demodulator probe at boot - No demodulator probe at boot
- No retry loops or integrity verification - No retry loops or integrity verification
- BCM4500 status polling reads 3 registers (0xA2, 0xA8, 0xA4) up to 6 times - BCM4500 status polling reads 3 registers (0xA2, 0xA8, 0xA4) up to 6 times
- Commands 0x99, 0x9A, 0x9C route to STALL - Commands 0x99, 0x9A, 0x9C route to STALL
- Command 0x9D reads descriptor byte and sets mode flag based on hardware revision (4, 5, or 6) - Command 0x9D reads descriptor byte and sets mode flag based on hardware revision (4, 5, or 6)
</TabItem> </TabItem>
</Tabs> </Tabs>
## Architectural Differences ## Architectural Differences
| Feature | Custom v3.05 | Custom v3.01 | v2.13 | Rev.2 v2.10 | v2.06 | | Feature | Custom v3.05 | Custom v3.01 | v2.13 | Rev.2 v2.10 | v2.06 |
|---------|--------------|--------------|-------|-------------|-------| |---------|--------------|--------------|-------|-------------|-------|
| Vendor commands | 30 stock + 18 custom | 30 stock + 7 custom | 30 | 27 | 30 | | Vendor commands | 30 stock + 18 custom | 30 stock + 7 custom | 30 | 27 | 30 |
| INT0 handler | N/A (fx2lib ISR) | N/A (fx2lib ISR) | Demod polling | USB re-enum | USB re-enum | | INT0 handler | N/A (fx2lib ISR) | N/A (fx2lib ISR) | Demod polling | USB re-enum | USB re-enum |
| Demod probe at boot | Yes (with timeout) | Yes (with timeout) | Yes (40 attempts) | No | No | | Demod probe at boot | Yes (with timeout) | Yes (with timeout) | Yes (40 attempts) | No | No |
| Retry loops | Yes (with timeout) | Yes (with timeout) | Yes (20-attempt) | No | No | | Retry loops | Yes (with timeout) | Yes (with timeout) | Yes (20-attempt) | No | No |
| HW revision detect | No | No | Yes (flag `_1_3`) | Yes (descriptor walker) | No | | HW revision detect | No | No | Yes (flag `_1_3`) | Yes (descriptor walker) | No |
| DiSEqC data pin | P0.7 | P0.7 | P0.0 | P0.4 | P0.7 | | DiSEqC data pin | P0.7 | P0.7 | P0.0 | P0.4 | P0.7 |
| Config byte IRAM addr | C variable | C variable | `0x4F` | `0x4E` | `0x6D` | | Config byte IRAM addr | C variable | C variable | `0x4F` | `0x4E` | `0x6D` |
| BCM4500 status poll | 1 register | 1 register | 1 register | 3 registers | 3 registers | | BCM4500 status poll | 1 register | 1 register | 1 register | 3 registers | 3 registers |
| I2C timeout | All paths (6000-count) | Helpers only (6000-count) | None | None | None | | I2C timeout | All paths (6000-count) | Helpers only (6000-count) | None | None | None |
| Software watchdog | Timer0 (2-second) | None | None | None | None | | Software watchdog | Timer0 (2-second) | None | None | None | None |
| EP0/GPIF/EP2 timeout | All protected | None | None | None | None | | EP0/GPIF/EP2 timeout | All protected | None | None | None | None |
| Error codes | 14 | 6 | N/A | N/A | N/A | | Error codes | 14 | 6 | N/A | N/A | N/A |
| Anti-tampering | No | No | Yes | No | No | | Anti-tampering | No | No | Yes | No | No |
| New commands | 0xB0--0xBE | 0xB0--0xB6 | 0x99, 0x9A, 0x9C | 0x99/0x9A proto | -- | | New commands | 0xB0--0xBE | 0xB0--0xB6 | 0x99, 0x9A, 0x9C | 0x99/0x9A proto | -- |
## Kernel Version Constants ## Kernel Version Constants
The Linux kernel driver defines two firmware version thresholds in `gp8psk-fe.h`: The Linux kernel driver defines two firmware version thresholds in `gp8psk-fe.h`:
```c title="Kernel firmware version constants" ```c title="Kernel firmware version constants"
GP8PSK_FW_REV1 = 0x020604 // v2.06.4 GP8PSK_FW_REV1 = 0x020604 // v2.06.4
GP8PSK_FW_REV2 = 0x020704 // v2.07.4 GP8PSK_FW_REV2 = 0x020704 // v2.07.4
``` ```
If the firmware version reported by `GET_FW_VERS` (command `0x92`) is >= `GP8PSK_FW_REV2`, the kernel enables Rev.2-specific code paths. All v2.10 and v2.13 firmwares are newer than either constant. If the firmware version reported by `GET_FW_VERS` (command `0x92`) is >= `GP8PSK_FW_REV2`, the kernel enables Rev.2-specific code paths. All v2.10 and v2.13 firmwares are newer than either constant.
<Aside type="caution" title="Version ID Gaps"> <Aside type="caution" title="Version ID Gaps">
`GP8PSK_FW_REV2` (`0x020704` = v2.07.04) is a **kernel threshold constant**, not an actual firmware release. No firmware with version 2.07.x was ever distributed. The real version progression is: `GP8PSK_FW_REV2` (`0x020704` = v2.07.04) is a **kernel threshold constant**, not an actual firmware release. No firmware with version 2.07.x was ever distributed. The real version progression is:
**v2.06.04** &rarr; **v2.10.04** &rarr; **v2.13.01** **v2.06.04** &rarr; **v2.10.04** &rarr; **v2.13.01**
Versions v2.07 through v2.09 and v2.11 through v2.12 do not exist. The kernel developers chose `0x020704` as a convenient threshold above the known v2.06.04 release. Versions v2.07 through v2.09 and v2.11 through v2.12 do not exist. The kernel developers chose `0x020704` as a convenient threshold above the known v2.06.04 release.
All three v2.13 sub-variants (FW1, FW2, FW3) report the same version ID `0x020D01` despite targeting different hardware. See [FW2.13 Variants](/firmware/fw213-variants/) for how they differ. All three v2.13 sub-variants (FW1, FW2, FW3) report the same version ID `0x020D01` despite targeting different hardware. See [FW2.13 Variants](/firmware/fw213-variants/) for how they differ.
</Aside> </Aside>
## Binary Similarity Matrix ## Binary Similarity Matrix
Byte-level comparison across the shared code length (percentage of identical bytes): Byte-level comparison across the shared code length (percentage of identical bytes):
| | v2.06 | v2.13.1 | v2.13.2 | v2.13.3 | Rev.2 | | | v2.06 | v2.13.1 | v2.13.2 | v2.13.3 | Rev.2 |
|---|---|---|---|---|---| |---|---|---|---|---|---|
| **v2.06** | -- | 4.8% | 4.3% | 4.3% | 6.0% | | **v2.06** | -- | 4.8% | 4.3% | 4.3% | 6.0% |
| **v2.13.1** | | -- | 57.2% | 59.4% | 8.0% | | **v2.13.1** | | -- | 57.2% | 59.4% | 8.0% |
| **v2.13.2** | | | -- | 83.5% | 5.8% | | **v2.13.2** | | | -- | 83.5% | 5.8% |
| **v2.13.3** | | | | -- | 5.8% | | **v2.13.3** | | | | -- | 5.8% |
| **Rev.2** | | | | | -- | | **Rev.2** | | | | | -- |
<Aside type="note"> <Aside type="note">
The extremely low similarity between major versions (4--8%) indicates complete recompilation with different linker configurations. Functions relocate to entirely different addresses even when the logic is identical. Only the vendor command dispatcher at `CODE:0056` maintains the same address across all versions. The extremely low similarity between major versions (4--8%) indicates complete recompilation with different linker configurations. Functions relocate to entirely different addresses even when the logic is identical. Only the vendor command dispatcher at `CODE:0056` maintains the same address across all versions.
</Aside> </Aside>
## Key Function Correspondence ## Key Function Correspondence
Functions that serve the same role but reside at different addresses: Functions that serve the same role but reside at different addresses:
| Role | v2.06 | Rev.2 | v2.13 | | Role | v2.06 | Rev.2 | v2.13 |
|------|-------|-------|-------| |------|-------|-------|-------|
| RESET vector / main | `0x188D` | `0x155F` | `0x170D` | | RESET vector / main | `0x188D` | `0x155F` | `0x170D` |
| Main init + loop | `0x09A7` | `0x09A9` | `0x0800` | | Main init + loop | `0x09A7` | `0x09A9` | `0x0800` |
| USB descriptor setup | `0x13C3` | `0x10D9` | `0x11AB` | | USB descriptor setup | `0x13C3` | `0x10D9` | `0x11AB` |
| Standard USB handler | `0x032A` | `0x0319` | `0x034E` | | Standard USB handler | `0x032A` | `0x0319` | `0x034E` |
| Vendor cmd dispatch | `0x0056` | `0x0056` | `0x0056` | | Vendor cmd dispatch | `0x0056` | `0x0056` | `0x0056` |
| Main loop poll | `0x2297` | -- | `0x21EC` | | Main loop poll | `0x2297` | -- | `0x21EC` |
| GPIF/FIFO management | `0x1919` | `0x0D7C` | `0x1800` | | GPIF/FIFO management | `0x1919` | `0x0D7C` | `0x1800` |
| BCM4500 firmware loader | `0x0DDD` | `0x0C64` | `0x0CA4` | | BCM4500 firmware loader | `0x0DDD` | `0x0C64` | `0x0CA4` |
| BCM4500 status polling | `0x2000` | -- | `0x208D` | | BCM4500 status polling | `0x2000` | -- | `0x208D` |
| Delay loop | `0x1DFB` | `0x1BDA` | `0x14B9` | | Delay loop | `0x1DFB` | `0x1BDA` | `0x14B9` |
## INT0 Handler Evolution ## INT0 Handler Evolution
The INT0 interrupt vector (`CODE:0003`) was repurposed between firmware generations: The INT0 interrupt vector (`CODE:0003`) was repurposed between firmware generations:
<Tabs> <Tabs>
<TabItem label="v2.06 / Rev.2"> <TabItem label="v2.06 / Rev.2">
**USB Re-enumeration** -- pulses CPUCS bit 3 to trigger controlled USB disconnect/reconnect: **USB Re-enumeration** -- pulses CPUCS bit 3 to trigger controlled USB disconnect/reconnect:
```c title="INT0 handler (v2.06 and Rev.2)" ```c title="INT0 handler (v2.06 and Rev.2)"
void INT0_vec(void) { void INT0_vec(void) {
if (flag == 0) CPUCS |= 0x08; // CPUCS bit 3 if (flag == 0) CPUCS |= 0x08; // CPUCS bit 3
else CPUCS |= 0x0A; // CPUCS bits 3+1 else CPUCS |= 0x0A; // CPUCS bits 3+1
delay(5, 0xDC); // ~1500 cycles delay(5, 0xDC); // ~1500 cycles
EPIRQ = 0xFF; // Clear endpoint IRQs EPIRQ = 0xFF; // Clear endpoint IRQs
USBIRQ = 0xFF; // Clear USB IRQs USBIRQ = 0xFF; // Clear USB IRQs
EXIF &= 0xEF; // Clear external interrupt flag EXIF &= 0xEF; // Clear external interrupt flag
CPUCS &= 0xF7; // Clear CPUCS bit 3 CPUCS &= 0xF7; // Clear CPUCS bit 3
} }
``` ```
</TabItem> </TabItem>
<TabItem label="v2.13"> <TabItem label="v2.13">
**Demodulator Availability Polling** -- probes two I2C addresses up to 40 times: **Demodulator Availability Polling** -- probes two I2C addresses up to 40 times:
```c title="INT0 handler (v2.13)" ```c title="INT0 handler (v2.13)"
void INT0_vector(void) { void INT0_vector(void) {
for (counter = 0x28; counter != 0; counter--) { for (counter = 0x28; counter != 0; counter--) {
byte result = I2C_read(0x7F); byte result = I2C_read(0x7F);
if (result != 0x01) { if (result != 0x01) {
result = I2C_read(0x3F); result = I2C_read(0x3F);
if (result != 0x01) break; if (result != 0x01) break;
} }
} }
no_demod_flag = (counter == 0); no_demod_flag = (counter == 0);
} }
``` ```
The USB re-enumeration logic was moved to `FUN_CODE_2031` and called as a normal function before the main loop. The USB re-enumeration logic was moved to `FUN_CODE_2031` and called as a normal function before the main loop.
</TabItem> </TabItem>
</Tabs> </Tabs>
## XRAM Initialization Table ## XRAM Initialization Table
All versions initialize FX2 peripheral registers from a CODE-space table at startup. The table format is identical: `[addr_hi] [addr_lo] [data_byte]` triplets terminated by `0x0000`. All versions initialize FX2 peripheral registers from a CODE-space table at startup. The table format is identical: `[addr_hi] [addr_lo] [data_byte]` triplets terminated by `0x0000`.
| Firmware | Table Address | Key Registers Set | | Firmware | Table Address | Key Registers Set |
|----------|--------------|-------------------| |----------|--------------|-------------------|
| v2.06 | `CODE:0B46` | IFCONFIG, EP2CFG, EP2FIFOCFG, REVCTL, I2CTL | | v2.06 | `CODE:0B46` | IFCONFIG, EP2CFG, EP2FIFOCFG, REVCTL, I2CTL |
| Rev.2 | `CODE:0B48` | Same set, 2 bytes later | | Rev.2 | `CODE:0B48` | Same set, 2 bytes later |
| v2.13 | `CODE:0B88` | Same set, different offsets | | v2.13 | `CODE:0B88` | Same set, different offsets |
All versions set the same final values: `IFCONFIG=0xEE`, `EP2CFG=0xE2`, `EP2FIFOCFG=0x0C`, `REVCTL=0x03`, `I2CTL=0x01`. All versions set the same final values: `IFCONFIG=0xEE`, `EP2CFG=0xE2`, `EP2FIFOCFG=0x0C`, `REVCTL=0x03`, `I2CTL=0x01`.
## Anti-Tampering (v2.13 Only) ## Anti-Tampering (v2.13 Only)
All v2.13 sub-variants contain this string at firmware offset `0x1880`: All v2.13 sub-variants contain this string at firmware offset `0x1880`:
``` ```
"Tampering is detected. Attempt is logged. Warranty is voided ! \n" "Tampering is detected. Attempt is logged. Warranty is voided ! \n"
``` ```
This is followed by I2C register write commands (`01 10 aa 82 02 41 41 83`). The mechanism is absent from v2.06, Rev.2, and the custom firmware. This is followed by I2C register write commands (`01 10 aa 82 02 41 41 83`). The mechanism is absent from v2.06, Rev.2, and the custom firmware.
## Version Identification ## Version Identification
The `GET_FW_VERS` command (`0x92`) returns 6 bytes of hardcoded constants: The `GET_FW_VERS` command (`0x92`) returns 6 bytes of hardcoded constants:
``` ```
Byte 0: version minor_minor (e.g., 0x04) Byte 0: version minor_minor (e.g., 0x04)
Byte 1: version minor (e.g., 0x06) Byte 1: version minor (e.g., 0x06)
Byte 2: version major (e.g., 0x02) Byte 2: version major (e.g., 0x02)
Byte 3: build day (e.g., 0x0D = 13) Byte 3: build day (e.g., 0x0D = 13)
Byte 4: build month (e.g., 0x07 = July) Byte 4: build month (e.g., 0x07 = July)
Byte 5: build year - 2000 (e.g., 0x07 = 2007) Byte 5: build year - 2000 (e.g., 0x07 = 2007)
``` ```
Full version = `byte[2] << 16 | byte[1] << 8 | byte[0]`. Build date = `(2000 + byte[5]) / byte[4] / byte[3]`. Full version = `byte[2] << 16 | byte[1] << 8 | byte[0]`. Build date = `(2000 + byte[5]) / byte[4] / byte[3]`.

View File

@ -1,322 +1,322 @@
--- ---
title: Applications & Use Cases title: Applications & Use Cases
description: What can the SkyWalker-1 actually do? Satellite TV, multi-standard signal analysis, radio astronomy, RF measurement, and more. description: What can the SkyWalker-1 actually do? Satellite TV, multi-standard signal analysis, radio astronomy, RF measurement, and more.
--- ---
import { Aside, Badge, Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components'; import { Aside, Badge, Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components';
The SkyWalker-1 shipped as a DVB-S satellite TV receiver. With [custom firmware](/firmware/custom-v305/) and The SkyWalker-1 shipped as a DVB-S satellite TV receiver. With [custom firmware](/firmware/custom-v305/) and
the reverse-engineered USB/I2C interface, it becomes something more interesting: a programmable RF instrument the reverse-engineered USB/I2C interface, it becomes something more interesting: a programmable RF instrument
covering 950-2150 MHz with ten demodulation modes, 256 Ksps to 30 Msps symbol rates, and full Python control. covering 950-2150 MHz with ten demodulation modes, 256 Ksps to 30 Msps symbol rates, and full Python control.
Here's what you can actually do with it. Here's what you can actually do with it.
## Satellite TV Reception ## Satellite TV Reception
The obvious one. The SkyWalker-1 receives free-to-air (FTA) DVB-S content — unencrypted satellite television The obvious one. The SkyWalker-1 receives free-to-air (FTA) DVB-S content — unencrypted satellite television
and radio that anyone with a dish can watch. and radio that anyone with a dish can watch.
### What's Up There ### What's Up There
<Tabs> <Tabs>
<TabItem label="Ku-Band"> <TabItem label="Ku-Band">
Most FTA content in North America lives on Ku-band satellites. A standard 30-36 inch dish and Most FTA content in North America lives on Ku-band satellites. A standard 30-36 inch dish and
universal LNB is all you need. universal LNB is all you need.
| Satellite | Position | What's On It | | Satellite | Position | What's On It |
|-----------|----------|-------------| |-----------|----------|-------------|
| Galaxy 19 | 97.0&deg;W | The FTA motherlode. ~135+ channels: Chinese, Korean, South Asian, religious, shopping, some English | | Galaxy 19 | 97.0&deg;W | The FTA motherlode. ~135+ channels: Chinese, Korean, South Asian, religious, shopping, some English |
| Galaxy 16 | 99.0&deg;W | Religious programming, international | | Galaxy 16 | 99.0&deg;W | Religious programming, international |
| SES-2 | 87.0&deg;W | International, government | | SES-2 | 87.0&deg;W | International, government |
| AMC-18 | 105.0&deg;W | Mixed FTA and encrypted | | AMC-18 | 105.0&deg;W | Mixed FTA and encrypted |
Typical tuning parameters: 11836 MHz V-pol, 20770 ksps, DVB-S QPSK FEC 3/4. Typical tuning parameters: 11836 MHz V-pol, 20770 ksps, DVB-S QPSK FEC 3/4.
</TabItem> </TabItem>
<TabItem label="C-Band"> <TabItem label="C-Band">
C-band requires a larger dish (6-12 feet) and a C-band LNB, but carries content that never made it C-band requires a larger dish (6-12 feet) and a C-band LNB, but carries content that never made it
to Ku-band — including DigiCipher II muxes that the SkyWalker-1 uniquely supports. to Ku-band — including DigiCipher II muxes that the SkyWalker-1 uniquely supports.
| Satellite | Position | What's On It | | Satellite | Position | What's On It |
|-----------|----------|-------------| |-----------|----------|-------------|
| AMC-18 | 105.0&deg;W | DCII cable distribution, some FTA | | AMC-18 | 105.0&deg;W | DCII cable distribution, some FTA |
| SES-2 | 87.0&deg;W | International, government feeds | | SES-2 | 87.0&deg;W | International, government feeds |
| Galaxy 16 | 99.0&deg;W | Mixed distribution | | Galaxy 16 | 99.0&deg;W | Mixed distribution |
The FCC C-band transition compressed services into the upper 3.98-4.2 GHz range. Additional The FCC C-band transition compressed services into the upper 3.98-4.2 GHz range. Additional
spectrum auctions are proposed for 2027 — C-band FTA is on borrowed time. spectrum auctions are proposed for 2027 — C-band FTA is on borrowed time.
</TabItem> </TabItem>
</Tabs> </Tabs>
### FTA Resources ### FTA Resources
Current channel listings change frequently. These sites track what's active: Current channel listings change frequently. These sites track what's active:
- [LyngSat](https://www.lyngsat.com/) — comprehensive transponder and channel database - [LyngSat](https://www.lyngsat.com/) — comprehensive transponder and channel database
- [SatExpat](https://www.satexpat.com/) — FTA channel listings with satellite footprints - [SatExpat](https://www.satexpat.com/) — FTA channel listings with satellite footprints
- [FTAList](https://ftalist.com/) — North American FTA community and channel guide - [FTAList](https://ftalist.com/) — North American FTA community and channel guide
<Aside type="caution" title="DVB-S2 is not supported"> <Aside type="caution" title="DVB-S2 is not supported">
An increasing percentage of satellite content uses **DVB-S2**, which relies on LDPC forward error correction An increasing percentage of satellite content uses **DVB-S2**, which relies on LDPC forward error correction
instead of the Reed-Solomon/Viterbi scheme the BCM4500 implements. The SkyWalker-1 can detect DVB-S2 instead of the Reed-Solomon/Viterbi scheme the BCM4500 implements. The SkyWalker-1 can detect DVB-S2
carriers as RF energy (they show up in spectrum sweeps), but it cannot demodulate or decode them. carriers as RF energy (they show up in spectrum sweeps), but it cannot demodulate or decode them.
If a transponder listing says "DVB-S2" or "8PSK" (in the DVB-S2 sense, not Turbo 8PSK), it won't work. If a transponder listing says "DVB-S2" or "8PSK" (in the DVB-S2 sense, not Turbo 8PSK), it won't work.
</Aside> </Aside>
## Multi-Standard Signal Analysis ## Multi-Standard Signal Analysis
This is where the SkyWalker-1 becomes genuinely rare hardware. The BCM4500 demodulates standards that are This is where the SkyWalker-1 becomes genuinely rare hardware. The BCM4500 demodulates standards that are
nearly extinct in available consumer equipment — standards that are still actively broadcasting. nearly extinct in available consumer equipment — standards that are still actively broadcasting.
<CardGrid> <CardGrid>
<Card title="DigiCipher II" icon="rocket"> <Card title="DigiCipher II" icon="rocket">
Cable headend distribution format (Comcast HITS, Motorola). One of very few modern devices with DCII Cable headend distribution format (Comcast HITS, Motorola). One of very few modern devices with DCII
support. "Zero Key" unencrypted services are directly receivable. support. "Zero Key" unencrypted services are directly receivable.
</Card> </Card>
<Card title="DSS" icon="star"> <Card title="DSS" icon="star">
Digital Satellite Service — legacy DirecTV format with 127-byte transport packets (vs 188-byte DVB). Digital Satellite Service — legacy DirecTV format with 127-byte transport packets (vs 188-byte DVB).
Extraordinarily rare outside DirecTV hardware. Extraordinarily rare outside DirecTV hardware.
</Card> </Card>
<Card title="Turbo 8PSK" icon="setting"> <Card title="Turbo 8PSK" icon="setting">
DISH Network transponder format. Encrypted content, but demodulator lock and transport stream capture DISH Network transponder format. Encrypted content, but demodulator lock and transport stream capture
work — useful for signal analysis and protocol research. work — useful for signal analysis and protocol research.
</Card> </Card>
<Card title="Turbo QPSK" icon="open-book"> <Card title="Turbo QPSK" icon="open-book">
Earlier turbo-coded variant. Better spectral efficiency than standard DVB-S QPSK, still used on Earlier turbo-coded variant. Better spectral efficiency than standard DVB-S QPSK, still used on
some distribution paths. some distribution paths.
</Card> </Card>
</CardGrid> </CardGrid>
### Why This Matters ### Why This Matters
These standards are still active on-air, but the hardware to receive them is disappearing. Off-the-shelf These standards are still active on-air, but the hardware to receive them is disappearing. Off-the-shelf
satellite receivers dropped DCII and DSS support years ago. The SkyWalker-1, through its BCM4500 demodulator, satellite receivers dropped DCII and DSS support years ago. The SkyWalker-1, through its BCM4500 demodulator,
retains these capabilities — making it a **preservation and research tool** for signal formats that will retains these capabilities — making it a **preservation and research tool** for signal formats that will
eventually go silent. eventually go silent.
The [TS Analyzer](/tools/ts-analyzer/) can parse transport streams from all supported modulation types, The [TS Analyzer](/tools/ts-analyzer/) can parse transport streams from all supported modulation types,
making it possible to compare DVB-S, DCII, and DSS packet structures side by side. making it possible to compare DVB-S, DCII, and DSS packet structures side by side.
See [BCM4500 Demodulator](/bcm4500/demodulator/) for register-level details on how each modulation type See [BCM4500 Demodulator](/bcm4500/demodulator/) for register-level details on how each modulation type
is configured. is configured.
## Wild Feed & Backhaul Hunting ## Wild Feed & Backhaul Hunting
Satellite transponders carry more than scheduled programming. Temporary unencrypted uplinks — "wild feeds" — Satellite transponders carry more than scheduled programming. Temporary unencrypted uplinks — "wild feeds" —
appear and disappear throughout the day: appear and disappear throughout the day:
- **Live news remotes**: Raw camera feeds from field reporters, unedited and uncensored - **Live news remotes**: Raw camera feeds from field reporters, unedited and uncensored
- **Sports backhauls**: Stadium camera feeds before production mixing - **Sports backhauls**: Stadium camera feeds before production mixing
- **Network distribution**: Programs fed to affiliates before air time - **Network distribution**: Programs fed to affiliates before air time
- **Event coverage**: Press conferences, hearings, launches - **Event coverage**: Press conferences, hearings, launches
The SkyWalker-1's blind scan capability and wide symbol rate range (256 Ksps - 30 Msps) make it well-suited The SkyWalker-1's blind scan capability and wide symbol rate range (256 Ksps - 30 Msps) make it well-suited
for finding these transient signals. The [Carrier Survey](/tools/survey/) tool automates the sweep-and-lock for finding these transient signals. The [Carrier Survey](/tools/survey/) tool automates the sweep-and-lock
cycle across a full satellite. cycle across a full satellite.
<Aside type="tip" title="Community resource"> <Aside type="tip" title="Community resource">
[Rick's Satellite Wildfeed Forum](https://www.satelliteguys.us/xen/forums/wild-feeds.42/) on SatelliteGuys [Rick's Satellite Wildfeed Forum](https://www.satelliteguys.us/xen/forums/wild-feeds.42/) on SatelliteGuys
is the primary community hub for reporting and tracking wild feeds on North American satellites. is the primary community hub for reporting and tracking wild feeds on North American satellites.
</Aside> </Aside>
## Radio Astronomy ## Radio Astronomy
The 950-2150 MHz IF range — or, without an LNB, the direct input range — overlaps with several The 950-2150 MHz IF range — or, without an LNB, the direct input range — overlaps with several
astrophysically interesting frequencies. The BCM4500's AGC registers respond to any RF energy at the astrophysically interesting frequencies. The BCM4500's AGC registers respond to any RF energy at the
tuned frequency, regardless of whether it carries a demodulatable signal. tuned frequency, regardless of whether it carries a demodulatable signal.
### Hydrogen 21 cm ### Hydrogen 21 cm
<Badge text="tools/h21cm.py" variant="note" /> <Badge text="tools/h21cm.py" variant="note" />
Neutral hydrogen emits at **1420.405 MHz** — directly in the IF range with no LNB. Connect an L-band Neutral hydrogen emits at **1420.405 MHz** — directly in the IF range with no LNB. Connect an L-band
antenna (patch, helical, or horn) to the F-connector and the SkyWalker-1 becomes a hydrogen line antenna (patch, helical, or horn) to the F-connector and the SkyWalker-1 becomes a hydrogen line
radiometer. The velocity-dispersed emission from the Milky Way's spiral arms is detectable even radiometer. The velocity-dispersed emission from the Milky Way's spiral arms is detectable even
with the BCM4500's ~346 kHz resolution bandwidth. with the BCM4500's ~346 kHz resolution bandwidth.
See [Hydrogen 21 cm Radiometer](/tools/h21cm/) for the full tool reference. See [Hydrogen 21 cm Radiometer](/tools/h21cm/) for the full tool reference.
### Ku-Band Solar Observation ### Ku-Band Solar Observation
Point a standard satellite dish + LNB at the Sun. At 10-12 GHz, solar thermal emission produces a Point a standard satellite dish + LNB at the Sun. At 10-12 GHz, solar thermal emission produces a
detectable **6+ dB rise** above the cold-sky background. Solar flares produce wideband bursts that detectable **6+ dB rise** above the cold-sky background. Solar flares produce wideband bursts that
are even more dramatic. are even more dramatic.
The SkyWalker-1's advantage over an RTL-SDR here is bandwidth: the 30 Msps sweep capability covers The SkyWalker-1's advantage over an RTL-SDR here is bandwidth: the 30 Msps sweep capability covers
a much wider swath of spectrum (~30 MHz effective) compared to the RTL-SDR's ~2.4 MHz, making it a much wider swath of spectrum (~30 MHz effective) compared to the RTL-SDR's ~2.4 MHz, making it
easier to detect and characterize broadband solar events. easier to detect and characterize broadband solar events.
Use the [Spectrum Analysis](/tools/spectrum-analysis/) sweep mode to build solar emission profiles. Use the [Spectrum Analysis](/tools/spectrum-analysis/) sweep mode to build solar emission profiles.
### Moon Thermal Emission ### Moon Thermal Emission
The Moon is a calibrated thermal source at microwave frequencies. Measuring its emission relative to The Moon is a calibrated thermal source at microwave frequencies. Measuring its emission relative to
cold sky provides a reference point for system noise temperature estimation — a standard radio cold sky provides a reference point for system noise temperature estimation — a standard radio
astronomy calibration technique. astronomy calibration technique.
## RF Test & Measurement ## RF Test & Measurement
The custom firmware turns the SkyWalker-1 into a basic but useful L-band test instrument. The custom firmware turns the SkyWalker-1 into a basic but useful L-band test instrument.
### L-Band Spectrum Analyzer ### L-Band Spectrum Analyzer
<Badge text="tools/skywalker.py spectrum" variant="note" /> <Badge text="tools/skywalker.py spectrum" variant="note" />
Sweep 950-2150 MHz in configurable steps, recording AGC power at each frequency. Not calibrated Sweep 950-2150 MHz in configurable steps, recording AGC power at each frequency. Not calibrated
to absolute dBm, but relative measurements are consistent enough for transponder identification, to absolute dBm, but relative measurements are consistent enough for transponder identification,
interference detection, and comparative analysis. interference detection, and comparative analysis.
See [Spectrum Analysis](/tools/spectrum-analysis/) for sweep techniques and interpretation. See [Spectrum Analysis](/tools/spectrum-analysis/) for sweep techniques and interpretation.
### CW Injection Test Bench ### CW Injection Test Bench
<Badge text="tools/rf_testbench.py" variant="note" /> <Badge text="tools/rf_testbench.py" variant="note" />
Connect a NanoVNA as a CW source through an [HMC472A digital attenuator](https://hmc472.l.zmesh.systems/) Connect a NanoVNA as a CW source through an [HMC472A digital attenuator](https://hmc472.l.zmesh.systems/)
to the SkyWalker-1's F-connector. The `rf_testbench.py` tool automates five test sequences: to the SkyWalker-1's F-connector. The `rf_testbench.py` tool automates five test sequences:
AGC linearity mapping, IF band flatness, frequency accuracy, minimum detectable signal, and AGC linearity mapping, IF band flatness, frequency accuracy, minimum detectable signal, and
BPSK mode 9 probing. The HMC472A provides 0-31.5 dB of programmable attenuation in 0.5 dB BPSK mode 9 probing. The HMC472A provides 0-31.5 dB of programmable attenuation in 0.5 dB
steps via its REST API, giving precision level control without swapping fixed pads. steps via its REST API, giving precision level control without swapping fixed pads.
See [RF Test Bench](/tools/rf-testbench/) for hardware setup, calibration, and test descriptions. See [RF Test Bench](/tools/rf-testbench/) for hardware setup, calibration, and test descriptions.
### LNB Characterization ### LNB Characterization
Measure gain flatness across the IF band by sweeping a known satellite's transponder plan and Measure gain flatness across the IF band by sweeping a known satellite's transponder plan and
comparing received power levels. Track LO drift over temperature by monitoring a stable carrier's comparing received power levels. Track LO drift over temperature by monitoring a stable carrier's
frequency offset over 24 hours with the [Beacon Logger](/tools/beacon-logger/). frequency offset over 24 hours with the [Beacon Logger](/tools/beacon-logger/).
The I2C-exposed tuner and demodulator registers make internal signal chain parameters directly The I2C-exposed tuner and demodulator registers make internal signal chain parameters directly
readable — something most consumer receivers hide completely. readable — something most consumer receivers hide completely.
### Transponder Fingerprinting ### Transponder Fingerprinting
Each satellite transponder has unique RF characteristics: center frequency, symbol rate, rolloff, Each satellite transponder has unique RF characteristics: center frequency, symbol rate, rolloff,
power level, modulation type. The [Carrier Survey](/tools/survey/) tool builds a catalog of these power level, modulation type. The [Carrier Survey](/tools/survey/) tool builds a catalog of these
parameters. Over time, this creates a fingerprint database useful for satellite identification parameters. Over time, this creates a fingerprint database useful for satellite identification
and change detection. and change detection.
### 5G Interference Monitoring ### 5G Interference Monitoring
The FCC's C-band auction reallocated 3.7-3.98 GHz to 5G operators. Spillover from 5G base stations The FCC's C-band auction reallocated 3.7-3.98 GHz to 5G operators. Spillover from 5G base stations
into the satellite C-band (3.98-4.2 GHz) is an increasing concern for satellite operators and into the satellite C-band (3.98-4.2 GHz) is an increasing concern for satellite operators and
earth station licensees. With a C-band LNB, the SkyWalker-1 can sweep the IF band and detect earth station licensees. With a C-band LNB, the SkyWalker-1 can sweep the IF band and detect
interference signatures. interference signatures.
## Propagation Science & Weather ## Propagation Science & Weather
Long-duration signal monitoring produces datasets that map directly to atmospheric physics. Long-duration signal monitoring produces datasets that map directly to atmospheric physics.
### Rain Fade Analysis ### Rain Fade Analysis
<Badge text="tools/beacon_logger.py" variant="note" /> <Badge text="tools/beacon_logger.py" variant="note" />
Lock onto a stable Ku-band transponder and log SNR at 1 Hz for days or weeks. Ku-band signals Lock onto a stable Ku-band transponder and log SNR at 1 Hz for days or weeks. Ku-band signals
attenuate predictably in rain — the ITU-R P.618 model describes the relationship between rainfall attenuate predictably in rain — the ITU-R P.618 model describes the relationship between rainfall
rate and attenuation at specific frequencies. Real measurement data validates (or challenges) rate and attenuation at specific frequencies. Real measurement data validates (or challenges)
these models for your specific location and dish geometry. these models for your specific location and dish geometry.
### Diurnal Thermal Effects ### Diurnal Thermal Effects
LNB gain varies with temperature. A 24-hour beacon log correlated with ambient temperature data LNB gain varies with temperature. A 24-hour beacon log correlated with ambient temperature data
reveals the thermal gain coefficient of your specific LNB — useful for separating real propagation reveals the thermal gain coefficient of your specific LNB — useful for separating real propagation
events from equipment drift. events from equipment drift.
### Link Budget Validation ### Link Budget Validation
Compare long-term average received signal levels against calculated link budgets (EIRP, free space Compare long-term average received signal levels against calculated link budgets (EIRP, free space
loss, atmospheric absorption, antenna gain, system noise temperature). The gap between prediction loss, atmospheric absorption, antenna gain, system noise temperature). The gap between prediction
and measurement is where engineering meets reality. and measurement is where engineering meets reality.
See [Beacon Logger](/tools/beacon-logger/) for unattended multi-day logging with auto-relock. See [Beacon Logger](/tools/beacon-logger/) for unattended multi-day logging with auto-relock.
## Education & Research ## Education & Research
The SkyWalker-1 exposes the complete satellite signal chain from RF input to MPEG-2 transport stream The SkyWalker-1 exposes the complete satellite signal chain from RF input to MPEG-2 transport stream
output, with every intermediate stage accessible over I2C. output, with every intermediate stage accessible over I2C.
### University Lab Platform ### University Lab Platform
A single SkyWalker-1 + dish + LNB covers a semester of satellite communications topics with A single SkyWalker-1 + dish + LNB covers a semester of satellite communications topics with
live signals: live signals:
| Topic | What's Observable | | Topic | What's Observable |
|-------|------------------| |-------|------------------|
| QPSK/8PSK demodulation | Lock status, constellation quality via SNR | | QPSK/8PSK demodulation | Lock status, constellation quality via SNR |
| Forward error correction | Viterbi, Reed-Solomon, Turbo code — switchable by modulation type | | Forward error correction | Viterbi, Reed-Solomon, Turbo code — switchable by modulation type |
| Link budgets | Real measurements vs. theoretical calculations | | Link budgets | Real measurements vs. theoretical calculations |
| MPEG-2 transport streams | Live PSI/SI table parsing, PID analysis | | MPEG-2 transport streams | Live PSI/SI table parsing, PID analysis |
| Spectrum analysis | Transponder identification from raw power sweeps | | Spectrum analysis | Transponder identification from raw power sweeps |
| Antenna pointing | Signal strength vs. azimuth/elevation in real time | | Antenna pointing | Signal strength vs. azimuth/elevation in real time |
### Transport Stream Protocol Research ### Transport Stream Protocol Research
The SkyWalker-1's multi-standard support makes it uniquely suited for comparative protocol analysis: The SkyWalker-1's multi-standard support makes it uniquely suited for comparative protocol analysis:
- **DVB-S**: 188-byte MPEG-2 TS packets, standard PID structure - **DVB-S**: 188-byte MPEG-2 TS packets, standard PID structure
- **DigiCipher II**: Motorola proprietary transport, conditional access - **DigiCipher II**: Motorola proprietary transport, conditional access
- **DSS**: 127-byte packets — shorter than DVB, different header format - **DSS**: 127-byte packets — shorter than DVB, different header format
Tools like [TSDuck](https://tsduck.io/) and dvbsnoop can parse captured streams. The [TS Analyzer](/tools/ts-analyzer/) Tools like [TSDuck](https://tsduck.io/) and dvbsnoop can parse captured streams. The [TS Analyzer](/tools/ts-analyzer/)
handles the initial capture and PSI extraction. handles the initial capture and PSI extraction.
### Accessible Signal Chain ### Accessible Signal Chain
The I2C bus provides direct read access to tuner, demodulator, and FEC status registers. Students can The I2C bus provides direct read access to tuner, demodulator, and FEC status registers. Students can
observe the AGC settling, watch the demodulator acquire lock, and read error correction statistics — observe the AGC settling, watch the demodulator acquire lock, and read error correction statistics —
the internal workings of the signal chain, visible in real time. See [I2C Bus Architecture](/i2c/bus-architecture/) the internal workings of the signal chain, visible in real time. See [I2C Bus Architecture](/i2c/bus-architecture/)
and [Signal Monitoring](/bcm4500/signal-monitoring/) for register details. and [Signal Monitoring](/bcm4500/signal-monitoring/) for register details.
## What's NOT Compatible ## What's NOT Compatible
Setting honest expectations is more valuable than overselling. Setting honest expectations is more valuable than overselling.
<Aside type="danger" title="Hardware limitations"> <Aside type="danger" title="Hardware limitations">
The following are common requests that the SkyWalker-1 **cannot** fulfill. Understanding these The following are common requests that the SkyWalker-1 **cannot** fulfill. Understanding these
boundaries prevents wasted time and money on incompatible setups. boundaries prevents wasted time and money on incompatible setups.
</Aside> </Aside>
| Signal / Application | Why Not | | Signal / Application | Why Not |
|---------------------|---------| |---------------------|---------|
| **DVB-S2** | Incompatible FEC — uses LDPC instead of Reed-Solomon/Viterbi. This is a growing percentage of satellite content. | | **DVB-S2** | Incompatible FEC — uses LDPC instead of Reed-Solomon/Viterbi. This is a growing percentage of satellite content. |
| **GOES weather satellite imagery** | LRIT uses BPSK/CCSDS (not DVB-S), GRB uses DVB-S2. Cannot decode imagery. However, the BCM4500's BPSK mode 9 uses the same inner FEC (Viterbi rate 1/2 K=7) as LRIT — the signal chain gets four stages deep before breaking at RS decoder block size and CCSDS framing. The LRIT carrier at 1694.1 MHz is within the [direct input range](/tools/h21cm/#antenna-setup) and can be used for antenna alignment and propagation monitoring. See [RF Test Bench](/tools/rf-testbench/) for BPSK mode 9 probing. | | **GOES weather satellite imagery** | LRIT uses BPSK/CCSDS (not DVB-S), GRB uses DVB-S2. Cannot decode imagery. However, the BCM4500's BPSK mode 9 uses the same inner FEC (Viterbi rate 1/2 K=7) as LRIT — the signal chain gets four stages deep before breaking at RS decoder block size and CCSDS framing. The LRIT carrier at 1694.1 MHz is within the [direct input range](/tools/h21cm/#antenna-setup) and can be used for antenna alignment and propagation monitoring. See [RF Test Bench](/tools/rf-testbench/) for BPSK mode 9 probing. |
| **QO-100 from North America** | Es'hail-2 is at 25.9&deg;E — visible from Europe, Africa, and the Middle East, but not North America. See [QO-100 DATV Reception](/guides/qo100-datv/) for coverage details. | | **QO-100 from North America** | Es'hail-2 is at 25.9&deg;E — visible from Europe, Africa, and the Middle East, but not North America. See [QO-100 DATV Reception](/guides/qo100-datv/) for coverage details. |
| **Military/government feeds** | Encrypted and increasingly DVB-S2 or proprietary modulation. | | **Military/government feeds** | Encrypted and increasingly DVB-S2 or proprietary modulation. |
| **ATSC / DVB-T terrestrial** | Completely different modulation family (OFDM), different frequency band. | | **ATSC / DVB-T terrestrial** | Completely different modulation family (OFDM), different frequency band. |
| **Analog satellite TV** | The BCM4500 is a digital demodulator. Analog satellite is also effectively extinct. | | **Analog satellite TV** | The BCM4500 is a digital demodulator. Analog satellite is also effectively extinct. |
## Modulation Support Reference ## Modulation Support Reference
<Tabs> <Tabs>
<TabItem label="By Standard"> <TabItem label="By Standard">
| Modulation | Standard | Typical Use | FTA Content? | | Modulation | Standard | Typical Use | FTA Content? |
|-----------|----------|-------------|-------------| |-----------|----------|-------------|-------------|
| DVB-S QPSK | DVB-S EN 300 421 | Free-to-air satellite TV worldwide | Yes — most FTA content | | DVB-S QPSK | DVB-S EN 300 421 | Free-to-air satellite TV worldwide | Yes — most FTA content |
| Turbo QPSK | Proprietary (Comstream) | Distribution, some DISH | Rare | | Turbo QPSK | Proprietary (Comstream) | Distribution, some DISH | Rare |
| Turbo 8PSK | Proprietary | DISH Network | No — encrypted | | Turbo 8PSK | Proprietary | DISH Network | No — encrypted |
| DCII Combo | Motorola DigiCipher II | Cable headend distribution | Some ("Zero Key") | | DCII Combo | Motorola DigiCipher II | Cable headend distribution | Some ("Zero Key") |
| DCII Split I | Motorola DigiCipher II | Cable headend distribution | Some | | DCII Split I | Motorola DigiCipher II | Cable headend distribution | Some |
| DCII Split Q | Motorola DigiCipher II | Cable headend distribution | Some | | DCII Split Q | Motorola DigiCipher II | Cable headend distribution | Some |
| DCII Offset QPSK | Motorola DigiCipher II | Cable headend distribution | Some | | DCII Offset QPSK | Motorola DigiCipher II | Cable headend distribution | Some |
| DSS QPSK | Hughes DSS | Legacy DirecTV | No — service winding down | | DSS QPSK | Hughes DSS | Legacy DirecTV | No — service winding down |
</TabItem> </TabItem>
<TabItem label="By Receiver Use"> <TabItem label="By Receiver Use">
| What You Want to Do | Modulation to Select | Symbol Rate Range | | What You Want to Do | Modulation to Select | Symbol Rate Range |
|--------------------|--------------------|------------------| |--------------------|--------------------|------------------|
| Watch FTA satellite TV | DVB-S QPSK | 2-30 Msps | | Watch FTA satellite TV | DVB-S QPSK | 2-30 Msps |
| Analyze DISH Network signals | Turbo 8PSK | 20-30 Msps | | Analyze DISH Network signals | Turbo 8PSK | 20-30 Msps |
| Receive DCII cable distribution | DCII Combo/Split/Offset | 2-30 Msps | | Receive DCII cable distribution | DCII Combo/Split/Offset | 2-30 Msps |
| Study DSS transport format | DSS QPSK | 20 Msps typical | | Study DSS transport format | DSS QPSK | 20 Msps typical |
| Hydrogen 21 cm (no LNB) | N/A — AGC power only | Any (for carrier lock attempt) | | Hydrogen 21 cm (no LNB) | N/A — AGC power only | Any (for carrier lock attempt) |
| Spectrum sweep / signal detection | N/A — AGC power only | Set during tune, not critical | | Spectrum sweep / signal detection | N/A — AGC power only | Set during tune, not critical |
</TabItem> </TabItem>
</Tabs> </Tabs>
## See Also ## See Also
- [RF Specifications](/hardware/rf-specifications/) — frequency range, symbol rate limits, LNB power - [RF Specifications](/hardware/rf-specifications/) — frequency range, symbol rate limits, LNB power
- [BCM4500 Demodulator](/bcm4500/demodulator/) — register-level modulation configuration - [BCM4500 Demodulator](/bcm4500/demodulator/) — register-level modulation configuration
- [Spectrum Analysis](/tools/spectrum-analysis/) — sweep techniques and transponder scanning - [Spectrum Analysis](/tools/spectrum-analysis/) — sweep techniques and transponder scanning
- [RF Test Bench](/tools/rf-testbench/) — CW injection testing with NanoVNA + HMC472A - [RF Test Bench](/tools/rf-testbench/) — CW injection testing with NanoVNA + HMC472A
- [Experimenter's Roadmap](/guides/experimenter-roadmap/) — future experiment tiers and creative applications - [Experimenter's Roadmap](/guides/experimenter-roadmap/) — future experiment tiers and creative applications
- [MCP Server](/tools/mcp-server/) — programmatic access to all hardware functions - [MCP Server](/tools/mcp-server/) — programmatic access to all hardware functions

View File

@ -1,218 +1,218 @@
--- ---
title: Experimenter's Roadmap title: Experimenter's Roadmap
description: What else can the SkyWalker-1 hardware do? A field guide to creative RF experiments beyond satellite TV reception. description: What else can the SkyWalker-1 hardware do? A field guide to creative RF experiments beyond satellite TV reception.
--- ---
import { Aside, Badge, Card, CardGrid, Steps, Tabs, TabItem } from '@astrojs/starlight/components'; import { Aside, Badge, Card, CardGrid, Steps, Tabs, TabItem } from '@astrojs/starlight/components';
The SkyWalker-1 reverse engineering project has produced a fully documented, custom-firmware-driven, The SkyWalker-1 reverse engineering project has produced a fully documented, custom-firmware-driven,
Python-controllable RF instrument. With v3.05.0 deployed and all 55 Hamilton safety tests passing, Python-controllable RF instrument. With v3.05.0 deployed and all 55 Hamilton safety tests passing,
the question becomes: **what can experimenters actually do with this platform beyond satellite TV reception?** the question becomes: **what can experimenters actually do with this platform beyond satellite TV reception?**
The approach: start from the hardware capabilities, ask "what physical processes produce or interact The approach: start from the hardware capabilities, ask "what physical processes produce or interact
with signals these capabilities can measure," and reason outward to creative applications. with signals these capabilities can measure," and reason outward to creative applications.
## Hardware as a Platform ## Hardware as a Platform
The SkyWalker-1 is simultaneously: The SkyWalker-1 is simultaneously:
- A **power meter** (16-bit AGC, ~30-40 dB dynamic range) - A **power meter** (16-bit AGC, ~30-40 dB dynamic range)
- A **spectrum analyzer** (~346 kHz RBW, 950-2150 MHz) - A **spectrum analyzer** (~346 kHz RBW, 950-2150 MHz)
- A **satellite receiver** (10 modulation types, 256 ksps - 30 Msps) - A **satellite receiver** (10 modulation types, 256 ksps - 30 Msps)
- A **time-series data logger** (signal_monitor at ~50 Hz) - A **time-series data logger** (signal_monitor at ~50 Hz)
- A **dish positioning system** (DiSEqC 1.2 motor, USALS GotoX) - A **dish positioning system** (DiSEqC 1.2 motor, USALS GotoX)
All controllable from Python. All controllable from Python.
<Aside type="tip" title="The key realization"> <Aside type="tip" title="The key realization">
The AGC registers respond to **any RF energy** at the tuned frequency, regardless of modulation. The AGC registers respond to **any RF energy** at the tuned frequency, regardless of modulation.
You don't need to demodulate a signal to detect and measure it. You don't need to demodulate a signal to detect and measure it.
</Aside> </Aside>
## What's Directly Receivable (No LNB) ## What's Directly Receivable (No LNB)
The 950-2150 MHz IF range contains far more than satellite TV when you connect an antenna directly: The 950-2150 MHz IF range contains far more than satellite TV when you connect an antenna directly:
| Frequency | What's There | Detectable? | | Frequency | What's There | Detectable? |
|---|---|---| |---|---|---|
| **1420.405 MHz** | Hydrogen 21 cm line — galactic emission | Yes (AGC power) | | **1420.405 MHz** | Hydrogen 21 cm line — galactic emission | Yes (AGC power) |
| 1575.42 MHz | GPS L1 | Yes (energy) | | 1575.42 MHz | GPS L1 | Yes (energy) |
| 1176.45 MHz | GPS L5 / Galileo E5a | Yes (energy) | | 1176.45 MHz | GPS L5 / Galileo E5a | Yes (energy) |
| 1227.6 MHz | GPS L2 | Yes (energy) | | 1227.6 MHz | GPS L2 | Yes (energy) |
| 1602 MHz | GLONASS L1 | Yes (energy) | | 1602 MHz | GLONASS L1 | Yes (energy) |
| 1525-1559 MHz | Inmarsat downlink | Yes (energy) | | 1525-1559 MHz | Inmarsat downlink | Yes (energy) |
| 1616-1626 MHz | Iridium downlink | Yes (burst energy) | | 1616-1626 MHz | Iridium downlink | Yes (burst energy) |
| 1670-1710 MHz | GOES LRIT, NOAA HRPT | Yes (carrier) | | 1670-1710 MHz | GOES LRIT, NOAA HRPT | Yes (carrier) |
| 1240-1300 MHz | Amateur 23 cm band | Yes (energy) | | 1240-1300 MHz | Amateur 23 cm band | Yes (energy) |
## Phase 1 Tools (Available Now) ## Phase 1 Tools (Available Now)
### Hydrogen 21 cm Drift-Scan Radiometer ### Hydrogen 21 cm Drift-Scan Radiometer
<Badge text="tools/h21cm.py" variant="note" /> <Badge text="tools/h21cm.py" variant="note" />
Neutral hydrogen emits at 1420.405 MHz — directly in the IF range. The Milky Way's spiral arms Neutral hydrogen emits at 1420.405 MHz — directly in the IF range. The Milky Way's spiral arms
create a velocity-dispersed emission profile detectable even with the BCM4500's resolution bandwidth. create a velocity-dispersed emission profile detectable even with the BCM4500's resolution bandwidth.
<Steps> <Steps>
1. Connect an L-band antenna (patch, helical, or horn) directly to the F-connector 1. Connect an L-band antenna (patch, helical, or horn) directly to the F-connector
2. Run `python h21cm.py` for a single sweep centered on 1420.405 MHz 2. Run `python h21cm.py` for a single sweep centered on 1420.405 MHz
3. Look for elevated power across the 1419-1421 MHz range (the hydrogen emission) 3. Look for elevated power across the 1419-1421 MHz range (the hydrogen emission)
4. Use `--drift --duration 3600` for a one-hour drift scan as Earth rotates 4. Use `--drift --duration 3600` for a one-hour drift scan as Earth rotates
5. Use `--averages 8` for 8x averaging to pull the signal from the noise 5. Use `--averages 8` for 8x averaging to pull the signal from the noise
</Steps> </Steps>
```bash ```bash
# Single sweep with 8x averaging # Single sweep with 8x averaging
python tools/h21cm.py --averages 8 python tools/h21cm.py --averages 8
# One-hour drift scan with CSV output # One-hour drift scan with CSV output
python tools/h21cm.py --drift --duration 3600 --averages 4 --output h21cm-data.csv python tools/h21cm.py --drift --duration 3600 --averages 4 --output h21cm-data.csv
# Include control band comparison # Include control band comparison
python tools/h21cm.py --averages 8 --control python tools/h21cm.py --averages 8 --control
``` ```
The velocity of the detected hydrogen is calculated from Doppler shift: The velocity of the detected hydrogen is calculated from Doppler shift:
**v = c × (f_rest f_observed) / f_rest**. This maps directly to the rotation curve **v = c × (f_rest f_observed) / f_rest**. This maps directly to the rotation curve
of the Milky Way. of the Milky Way.
### Beacon Logger ### Beacon Logger
<Badge text="tools/beacon_logger.py" variant="note" /> <Badge text="tools/beacon_logger.py" variant="note" />
Lock onto a stable Ku-band broadcast transponder and log SNR/AGC at configurable intervals Lock onto a stable Ku-band broadcast transponder and log SNR/AGC at configurable intervals
for hours, days, or weeks. Produces propagation datasets useful for: for hours, days, or weeks. Produces propagation datasets useful for:
- **Rain fade analysis** — correlate attenuation with rainfall rate - **Rain fade analysis** — correlate attenuation with rainfall rate
- **Diurnal thermal drift** — track LNB gain vs. temperature over 24 hours - **Diurnal thermal drift** — track LNB gain vs. temperature over 24 hours
- **Antenna mount stability** — detect dish drift from wind/thermal expansion - **Antenna mount stability** — detect dish drift from wind/thermal expansion
- **ITU propagation model validation** — contribute real measurements - **ITU propagation model validation** — contribute real measurements
```bash ```bash
# Log a Ku-band beacon for 24 hours, 1 sample/sec, report every minute # Log a Ku-band beacon for 24 hours, 1 sample/sec, report every minute
python tools/beacon_logger.py --freq 1265000 --sr 20000000 \ python tools/beacon_logger.py --freq 1265000 --sr 20000000 \
--output beacon-24h.csv --json-output beacon-stats.jsonl \ --output beacon-24h.csv --json-output beacon-stats.jsonl \
--duration 86400 --duration 86400
# Generate a systemd unit file for unattended operation # Generate a systemd unit file for unattended operation
python tools/beacon_logger.py --generate-systemd \ python tools/beacon_logger.py --generate-systemd \
--freq 1265000 --sr 20000000 --output /var/log/beacon.csv --freq 1265000 --sr 20000000 --output /var/log/beacon.csv
``` ```
The logger automatically re-locks on signal loss and computes per-interval statistics The logger automatically re-locks on signal loss and computes per-interval statistics
(min/max/mean/stddev of SNR). (min/max/mean/stddev of SNR).
### Multi-Satellite Arc Survey ### Multi-Satellite Arc Survey
<Badge text="tools/arc_survey.py" variant="note" /> <Badge text="tools/arc_survey.py" variant="note" />
Automated "satellite census": points the dish motor to each GEO orbital longitude, Automated "satellite census": points the dish motor to each GEO orbital longitude,
runs a full-band six-stage survey at each position, and aggregates results into a comprehensive sky map. runs a full-band six-stage survey at each position, and aggregates results into a comprehensive sky map.
```bash ```bash
# Survey specific North American slots # Survey specific North American slots
python tools/arc_survey.py --observer-lon -96.8 --slots "97W,99W,101W,103W" python tools/arc_survey.py --observer-lon -96.8 --slots "97W,99W,101W,103W"
# Survey an arc at 3-degree intervals # Survey an arc at 3-degree intervals
python tools/arc_survey.py --observer-lon -96.8 --arc -120 -60 --step 3 python tools/arc_survey.py --observer-lon -96.8 --arc -120 -60 --step 3
# List common NA orbital slots # List common NA orbital slots
python tools/arc_survey.py --list-slots python tools/arc_survey.py --list-slots
# Resume an interrupted survey # Resume an interrupted survey
python tools/arc_survey.py --resume ~/.skywalker1/arc-surveys/arc-survey-2026-02-17.json python tools/arc_survey.py --resume ~/.skywalker1/arc-surveys/arc-survey-2026-02-17.json
``` ```
<Aside type="caution" title="Time commitment"> <Aside type="caution" title="Time commitment">
Each orbital slot takes 5-15 minutes to survey. A full North American arc Each orbital slot takes 5-15 minutes to survey. A full North American arc
(~35 positions) is an overnight operation. The tool saves progress after each (~35 positions) is an overnight operation. The tool saves progress after each
slot, so Ctrl-C pauses safely and `--resume` continues where you left off. slot, so Ctrl-C pauses safely and `--resume` continues where you left off.
</Aside> </Aside>
### MCP Server ### MCP Server
<Badge text="mcp/skywalker-mcp/" variant="note" /> <Badge text="mcp/skywalker-mcp/" variant="note" />
The `skywalker-mcp` FastMCP server wraps the entire hardware API as MCP tools, making The `skywalker-mcp` FastMCP server wraps the entire hardware API as MCP tools, making
every function accessible to LLMs. This is the foundation for autonomous RF exploration. every function accessible to LLMs. This is the foundation for autonomous RF exploration.
```bash ```bash
# Install and run (from project directory) # Install and run (from project directory)
cd mcp/skywalker-mcp && uv run skywalker-mcp cd mcp/skywalker-mcp && uv run skywalker-mcp
# Add to Claude Code # Add to Claude Code
claude mcp add skywalker-mcp -- uv run --directory mcp/skywalker-mcp skywalker-mcp claude mcp add skywalker-mcp -- uv run --directory mcp/skywalker-mcp skywalker-mcp
# Test with headless mode # Test with headless mode
claude -p "What firmware version is loaded?" \ claude -p "What firmware version is loaded?" \
--mcp-config .mcp.json --allowedTools "mcp__skywalker-mcp__*" --mcp-config .mcp.json --allowedTools "mcp__skywalker-mcp__*"
``` ```
**20 MCP tools** covering: **20 MCP tools** covering:
- Device status and signal quality - Device status and signal quality
- Spectrum sweep with peak detection - Spectrum sweep with peak detection
- Frequency tuning across 10 modulation types - Frequency tuning across 10 modulation types
- Blind scan for unknown carriers - Blind scan for unknown carriers
- Six-stage carrier survey with catalog persistence - Six-stage carrier survey with catalog persistence
- Dish motor control (jog, goto, USALS) - Dish motor control (jog, goto, USALS)
- LNB configuration - LNB configuration
- I2C bus scanning - I2C bus scanning
- Transport stream capture and PSI parsing - Transport stream capture and PSI parsing
- Frequency identification against allocation tables - Frequency identification against allocation tables
**MCP Resources:** **MCP Resources:**
- `skywalker://status` — live device state - `skywalker://status` — live device state
- `skywalker://catalog/latest` — most recent survey - `skywalker://catalog/latest` — most recent survey
- `skywalker://allocations/lband` — frequency allocation table - `skywalker://allocations/lband` — frequency allocation table
- `skywalker://modulations` — supported modulation types - `skywalker://modulations` — supported modulation types
**MCP Prompts:** **MCP Prompts:**
- `explore_rf_environment` — autonomous RF exploration strategy - `explore_rf_environment` — autonomous RF exploration strategy
- `hydrogen_line_observation` — guided hydrogen 21 cm procedure - `hydrogen_line_observation` — guided hydrogen 21 cm procedure
## Future Tiers ## Future Tiers
### Tier B: Creative Combinations (no firmware changes) ### Tier B: Creative Combinations (no firmware changes)
| Idea | Description | | Idea | Description |
|---|---| |---|---|
| **Gradient-descent dish auto-peaking** | Closed-loop: tune to beacon, read AGC, step motor, converge | | **Gradient-descent dish auto-peaking** | Closed-loop: tune to beacon, read AGC, step motor, converge |
| **Rain fade monitor** | Dual-frequency SNR logging + weather API correlation | | **Rain fade monitor** | Dual-frequency SNR logging + weather API correlation |
| **NIT-driven survey** | Parse NIT from one carrier → skip to ALL transponders | | **NIT-driven survey** | Parse NIT from one carrier → skip to ALL transponders |
| **Spectral anomaly detection** | Build baseline, flag N-sigma deviations, catch interference | | **Spectral anomaly detection** | Build baseline, flag N-sigma deviations, catch interference |
| **PCR timing analysis** | Extract clock jitter from transport stream timestamps | | **PCR timing analysis** | Extract clock jitter from transport stream timestamps |
### Tier C: Firmware Enhancements (v4.x) ### Tier C: Firmware Enhancements (v4.x)
| Feature | Impact | Size | | Feature | Impact | Size |
|---|---|---| |---|---|---|
| Continuous AGC streaming via EP2 | Real-time waterfall displays | ~100 bytes | | Continuous AGC streaming via EP2 | Real-time waterfall displays | ~100 bytes |
| Firmware-side moving average | 12 dB noise floor improvement (16x avg) | ~50 bytes | | Firmware-side moving average | 12 dB noise floor improvement (16x avg) | ~50 bytes |
| GPIO event counter via Timer1 | General-purpose frequency counter | ~80 bytes | | GPIO event counter via Timer1 | General-purpose frequency counter | ~80 bytes |
| Multi-byte I2C transactions | External sensor integration | ~120 bytes | | Multi-byte I2C transactions | External sensor integration | ~120 bytes |
| Fast power-only read (no retune) | 2x measurement rate | ~30 bytes | | Fast power-only read (no retune) | 2x measurement rate | ~30 bytes |
### Tier D: External Hardware ### Tier D: External Hardware
- **I2C environmental sensors** (BME280/SHT40) for LNB drift vs. temperature - **I2C environmental sensors** (BME280/SHT40) for LNB drift vs. temperature
- **External TCXO/OCXO reference** for calibrated LNB frequency (±50 Hz vs ±5 MHz) - **External TCXO/OCXO reference** for calibrated LNB frequency (±50 Hz vs ±5 MHz)
- **Noise source + Y-factor calibration** for absolute power measurements - **Noise source + Y-factor calibration** for absolute power measurements
- **GPIO antenna switch matrix** for automated antenna comparison - **GPIO antenna switch matrix** for automated antenna comparison
## Who Gets What ## Who Gets What
<CardGrid> <CardGrid>
<Card title="RF Phreaks" icon="rocket"> <Card title="RF Phreaks" icon="rocket">
Iridium burst detector, arc survey, anomaly detection, MCP autonomous explorer Iridium burst detector, arc survey, anomaly detection, MCP autonomous explorer
</Card> </Card>
<Card title="Ham Radio" icon="open-book"> <Card title="Ham Radio" icon="open-book">
Hydrogen line, dish auto-peaking, QO-100 monitoring, arc survey Hydrogen line, dish auto-peaking, QO-100 monitoring, arc survey
</Card> </Card>
<Card title="Skywatchers" icon="star"> <Card title="Skywatchers" icon="star">
Hydrogen line, GNSS monitoring, arc survey, beacon logger Hydrogen line, GNSS monitoring, arc survey, beacon logger
</Card> </Card>
<Card title="Engineers" icon="setting"> <Card title="Engineers" icon="setting">
Beacon logger, rain fade monitor, polarization analysis, PCR timing Beacon logger, rain fade monitor, polarization analysis, PCR timing
</Card> </Card>
</CardGrid> </CardGrid>

View File

@ -1,175 +1,175 @@
--- ---
title: QO-100 DATV Reception title: QO-100 DATV Reception
description: Receiving amateur digital television from the Es'hail-2 geostationary satellite using the SkyWalker-1 DVB-S receiver. description: Receiving amateur digital television from the Es'hail-2 geostationary satellite using the SkyWalker-1 DVB-S receiver.
--- ---
import { Tabs, TabItem, Steps, Aside, Badge, CardGrid, Card } from '@astrojs/starlight/components'; import { Tabs, TabItem, Steps, Aside, Badge, CardGrid, Card } from '@astrojs/starlight/components';
The Es'hail-2 satellite (25.9 degrees East) carries the first geostationary amateur radio transponders, designated QO-100. The wideband transponder at 10491-10499 MHz carries DATV (Digital Amateur Television) signals that the SkyWalker-1 can receive — with some important caveats about symbol rate limitations and LNB selection. The Es'hail-2 satellite (25.9 degrees East) carries the first geostationary amateur radio transponders, designated QO-100. The wideband transponder at 10491-10499 MHz carries DATV (Digital Amateur Television) signals that the SkyWalker-1 can receive — with some important caveats about symbol rate limitations and LNB selection.
<Badge text="Requires custom firmware v3.03.0+" variant="caution" /> <Badge text="Requires custom firmware v3.03.0+" variant="caution" />
## Overview ## Overview
<CardGrid> <CardGrid>
<Card title="Wideband Transponder" icon="rocket"> <Card title="Wideband Transponder" icon="rocket">
10491.000 - 10499.500 MHz (8.5 MHz bandwidth). Carries DVB-S DATV stations from amateur operators worldwide. 10491.000 - 10499.500 MHz (8.5 MHz bandwidth). Carries DVB-S DATV stations from amateur operators worldwide.
</Card> </Card>
<Card title="Engineering Beacon" icon="star"> <Card title="Engineering Beacon" icon="star">
10489.750 MHz CW/PSK beacon. Useful for dish pointing and LNB drift calibration. 10489.750 MHz CW/PSK beacon. Useful for dish pointing and LNB drift calibration.
</Card> </Card>
<Card title="Orbital Position" icon="sun"> <Card title="Orbital Position" icon="sun">
25.9 degrees East — visible from Europe, Africa, western Asia, and eastern Americas. 25.9 degrees East — visible from Europe, Africa, western Asia, and eastern Americas.
</Card> </Card>
<Card title="Minimum Dish Size" icon="setting"> <Card title="Minimum Dish Size" icon="setting">
60 cm in central Europe, 1.2m+ at the edges of the footprint. 60 cm in central Europe, 1.2m+ at the edges of the footprint.
</Card> </Card>
</CardGrid> </CardGrid>
## LNB Selection ## LNB Selection
The SkyWalker-1 accepts IF frequencies in the 950-2150 MHz range. The LNB's local oscillator frequency determines where the QO-100 signals appear in this window. The SkyWalker-1 accepts IF frequencies in the 950-2150 MHz range. The LNB's local oscillator frequency determines where the QO-100 signals appear in this window.
| LNB Type | LO Frequency | QO-100 IF Range | Compatible? | | LNB Type | LO Frequency | QO-100 IF Range | Compatible? |
|----------|-------------|-----------------|-------------| |----------|-------------|-----------------|-------------|
| Universal (low band) | 9750 MHz | 741-749 MHz | No — below 950 MHz minimum | | Universal (low band) | 9750 MHz | 741-749 MHz | No — below 950 MHz minimum |
| Universal (high band) | 10600 MHz | -109 to -101 MHz | No — negative IF | | Universal (high band) | 10600 MHz | -109 to -101 MHz | No — negative IF |
| Modified universal | 9361 MHz | 1130-1138 MHz | Yes | | Modified universal | 9361 MHz | 1130-1138 MHz | Yes |
| TCXO/PLL stabilized | 9750 MHz | 741-749 MHz | No — same issue | | TCXO/PLL stabilized | 9750 MHz | 741-749 MHz | No — same issue |
| Custom downconverter | varies | varies | Check IF range | | Custom downconverter | varies | varies | Check IF range |
<Aside type="caution"> <Aside type="caution">
A **standard universal LNB** at 9750 MHz places the QO-100 wideband transponder at 741-749 MHz IF, which is **below the SkyWalker-1's 950 MHz minimum**. You need either a modified LNB or an external downconverter to shift the IF into the 950-2150 MHz range. A **standard universal LNB** at 9750 MHz places the QO-100 wideband transponder at 741-749 MHz IF, which is **below the SkyWalker-1's 950 MHz minimum**. You need either a modified LNB or an external downconverter to shift the IF into the 950-2150 MHz range.
</Aside> </Aside>
### Modified LNB Option ### Modified LNB Option
The most common approach among QO-100 operators is modifying a universal LNB by replacing the crystal oscillator (typically 25 MHz) with one that produces a different LO frequency. A 24.000 MHz crystal in a universal LNB that normally multiplies by 390 (9750 MHz) will produce 9360 MHz instead, placing QO-100 at 1131-1139 MHz IF. The most common approach among QO-100 operators is modifying a universal LNB by replacing the crystal oscillator (typically 25 MHz) with one that produces a different LO frequency. A 24.000 MHz crystal in a universal LNB that normally multiplies by 390 (9750 MHz) will produce 9360 MHz instead, placing QO-100 at 1131-1139 MHz IF.
Popular modified LO frequencies and their resulting IF ranges: Popular modified LO frequencies and their resulting IF ranges:
| Crystal | Multiplier | LO (MHz) | QO-100 IF (MHz) | | Crystal | Multiplier | LO (MHz) | QO-100 IF (MHz) |
|---------|-----------|----------|-----------------| |---------|-----------|----------|-----------------|
| 24.000 MHz | x390 | 9360 | 1131-1139 | | 24.000 MHz | x390 | 9360 | 1131-1139 |
| 24.385 MHz | x384 | 9363 | 1128-1136 | | 24.385 MHz | x384 | 9363 | 1128-1136 |
| 25.000 MHz | x374 | 9350 | 1141-1149 | | 25.000 MHz | x374 | 9350 | 1141-1149 |
| 27.000 MHz | x348 | 9396 | 1095-1103 | | 27.000 MHz | x348 | 9396 | 1095-1103 |
## Quick Start ## Quick Start
<Steps> <Steps>
1. **Verify LNB compatibility** — check that your LO frequency places QO-100 in the 950-2150 MHz range: 1. **Verify LNB compatibility** — check that your LO frequency places QO-100 in the 950-2150 MHz range:
```bash ```bash
python3 tools/qo100.py calc --lnb-lo 9361 python3 tools/qo100.py calc --lnb-lo 9361
``` ```
2. **Point the dish** — aim at 25.9 degrees East. Use the motor control tool or manual positioning: 2. **Point the dish** — aim at 25.9 degrees East. Use the motor control tool or manual positioning:
```bash ```bash
sudo python3 tools/motor.py gotox --sat 25.9 --lon -97.5 sudo python3 tools/motor.py gotox --sat 25.9 --lon -97.5
``` ```
3. **Scan for carriers** — sweep the QO-100 IF range: 3. **Scan for carriers** — sweep the QO-100 IF range:
```bash ```bash
sudo python3 tools/qo100.py scan --lnb-lo 9361 sudo python3 tools/qo100.py scan --lnb-lo 9361
``` ```
4. **Tune to a carrier** — lock onto a detected DATV station: 4. **Tune to a carrier** — lock onto a detected DATV station:
```bash ```bash
sudo python3 tools/qo100.py tune --freq 1135 --sr 1000 --lnb-lo 9361 sudo python3 tools/qo100.py tune --freq 1135 --sr 1000 --lnb-lo 9361
``` ```
5. **Watch live video** — pipe the transport stream to a media player: 5. **Watch live video** — pipe the transport stream to a media player:
```bash ```bash
sudo python3 tools/qo100.py watch --freq 1135 --sr 1000 --lnb-lo 9361 sudo python3 tools/qo100.py watch --freq 1135 --sr 1000 --lnb-lo 9361
``` ```
</Steps> </Steps>
## CLI Reference ## CLI Reference
### Calculate IF Frequencies ### Calculate IF Frequencies
```bash ```bash
python3 tools/qo100.py calc --lnb-lo 9361 python3 tools/qo100.py calc --lnb-lo 9361
``` ```
Displays the QO-100 wideband transponder IF range, known DATV frequencies with their IF equivalents, and the beacon frequency. No hardware required — pure calculation. Displays the QO-100 wideband transponder IF range, known DATV frequencies with their IF equivalents, and the beacon frequency. No hardware required — pure calculation.
### Band Plan ### Band Plan
```bash ```bash
python3 tools/qo100.py band-plan --lnb-lo 9361 python3 tools/qo100.py band-plan --lnb-lo 9361
``` ```
Shows the complete QO-100 wideband transponder band plan with known station frequencies converted to your LNB's IF range. Includes both the wideband DATV segment and the engineering beacon. Shows the complete QO-100 wideband transponder band plan with known station frequencies converted to your LNB's IF range. Includes both the wideband DATV segment and the engineering beacon.
### Scan ### Scan
```bash ```bash
sudo python3 tools/qo100.py scan --lnb-lo 9361 sudo python3 tools/qo100.py scan --lnb-lo 9361
``` ```
Sweeps the QO-100 IF range with parameters tuned for narrowband DATV: Sweeps the QO-100 IF range with parameters tuned for narrowband DATV:
- 250 kHz frequency steps (vs 5 MHz for broadcast) - 250 kHz frequency steps (vs 5 MHz for broadcast)
- 1000 ksps measurement symbol rate - 1000 ksps measurement symbol rate
- Extended dwell time for weak signal detection - Extended dwell time for weak signal detection
### Tune ### Tune
```bash ```bash
sudo python3 tools/qo100.py tune --freq 1135 --sr 1000 --lnb-lo 9361 sudo python3 tools/qo100.py tune --freq 1135 --sr 1000 --lnb-lo 9361
``` ```
Tunes the BCM4500 to the specified IF frequency and symbol rate, then monitors lock status and signal quality. The `--freq` parameter is the IF frequency (after LNB downconversion), not the RF frequency. Tunes the BCM4500 to the specified IF frequency and symbol rate, then monitors lock status and signal quality. The `--freq` parameter is the IF frequency (after LNB downconversion), not the RF frequency.
### Watch ### Watch
```bash ```bash
sudo python3 tools/qo100.py watch --freq 1135 --sr 1000 --lnb-lo 9361 sudo python3 tools/qo100.py watch --freq 1135 --sr 1000 --lnb-lo 9361
``` ```
Tunes, locks, and pipes the raw MPEG-2 transport stream to `ffplay` (or `mpv` if ffplay is not found). The video player receives the stream on stdin and renders it in real time. Tunes, locks, and pipes the raw MPEG-2 transport stream to `ffplay` (or `mpv` if ffplay is not found). The video player receives the stream on stdin and renders it in real time.
| Flag | Default | Description | | Flag | Default | Description |
|------|---------|-------------| |------|---------|-------------|
| `--freq` | — | IF frequency in MHz (required) | | `--freq` | — | IF frequency in MHz (required) |
| `--sr` | 1000 | Symbol rate in ksps | | `--sr` | 1000 | Symbol rate in ksps |
| `--lnb-lo` | — | LNB local oscillator in MHz (required) | | `--lnb-lo` | — | LNB local oscillator in MHz (required) |
| `--player` | auto | Video player command (`ffplay` or `mpv`) | | `--player` | auto | Video player command (`ffplay` or `mpv`) |
## Hardware Limitations ## Hardware Limitations
### Minimum Symbol Rate ### Minimum Symbol Rate
The BCM4500 demodulator has a minimum symbol rate of **256 ksps** (256,000 symbols per second). Many QO-100 DATV stations transmit at lower rates: The BCM4500 demodulator has a minimum symbol rate of **256 ksps** (256,000 symbols per second). Many QO-100 DATV stations transmit at lower rates:
| Typical QO-100 SR | BCM4500 Support | | Typical QO-100 SR | BCM4500 Support |
|-------------------|----------------| |-------------------|----------------|
| 125 ksps | Detectable as energy, cannot lock | | 125 ksps | Detectable as energy, cannot lock |
| 250 ksps | Marginal — may lock with strong signal | | 250 ksps | Marginal — may lock with strong signal |
| 333 ksps | Supported | | 333 ksps | Supported |
| 500 ksps | Supported | | 500 ksps | Supported |
| 1000 ksps | Supported | | 1000 ksps | Supported |
| 2000 ksps | Supported | | 2000 ksps | Supported |
The survey tool distinguishes "carrier detected" (energy above noise floor) from "carrier locked" (BCM4500 achieved demodulator lock) in its output. The survey tool distinguishes "carrier detected" (energy above noise floor) from "carrier locked" (BCM4500 achieved demodulator lock) in its output.
### Lock Acquisition Time ### Lock Acquisition Time
QO-100 signals are weaker than broadcast satellites. The BCM4500 may need 10-30 seconds to achieve lock at low symbol rates, compared to 1-2 seconds for typical broadcast transponders. The `qo100.py tune` command uses extended timeouts automatically. QO-100 signals are weaker than broadcast satellites. The BCM4500 may need 10-30 seconds to achieve lock at low symbol rates, compared to 1-2 seconds for typical broadcast transponders. The `qo100.py tune` command uses extended timeouts automatically.
### Frequency Stability ### Frequency Stability
QO-100 DATV signals have tighter frequency tolerance requirements than the SkyWalker-1's default tuning resolution. A PLL-stabilized or TCXO LNB provides better frequency accuracy than a standard DRO LNB, reducing the chance of the demodulator losing lock due to LNB drift. QO-100 DATV signals have tighter frequency tolerance requirements than the SkyWalker-1's default tuning resolution. A PLL-stabilized or TCXO LNB provides better frequency accuracy than a standard DRO LNB, reducing the chance of the demodulator losing lock due to LNB drift.
## Using the TUI ## Using the TUI
The SkyWalker TUI includes QO-100 as a tab within the Survey screen (<kbd>F10</kbd>). The QO-100 tab pre-fills the sweep parameters with values optimized for the wideband transponder and includes an info panel showing known station frequencies adjusted for your LNB's local oscillator. The SkyWalker TUI includes QO-100 as a tab within the Survey screen (<kbd>F10</kbd>). The QO-100 tab pre-fills the sweep parameters with values optimized for the wideband transponder and includes an info panel showing known station frequencies adjusted for your LNB's local oscillator.
See [SkyWalker TUI — Survey Screen](/tools/tui/#survey--qo-100) for details. See [SkyWalker TUI — Survey Screen](/tools/tui/#survey--qo-100) for details.
## See Also ## See Also
- [Motor Control](/tools/motor/) — DiSEqC 1.2 positioner for dish pointing - [Motor Control](/tools/motor/) — DiSEqC 1.2 positioner for dish pointing
- [Carrier Survey](/tools/survey/) — automated carrier detection and cataloging - [Carrier Survey](/tools/survey/) — automated carrier detection and cataloging
- [LNB Control](/lnb-diseqc/lnb-control/) — LNB power and voltage configuration - [LNB Control](/lnb-diseqc/lnb-control/) — LNB power and voltage configuration
- [RF Specifications](/hardware/rf-specifications/) — SkyWalker-1 frequency range and sensitivity - [RF Specifications](/hardware/rf-specifications/) — SkyWalker-1 frequency range and sensitivity

View File

@ -1,131 +1,131 @@
--- ---
title: GPIO Pin Map title: GPIO Pin Map
description: Complete FX2 GPIO pin assignments across all firmware versions including stock and custom firmware. description: Complete FX2 GPIO pin assignments across all firmware versions including stock and custom firmware.
--- ---
import { Tabs, TabItem, Badge, Aside } from '@astrojs/starlight/components'; import { Tabs, TabItem, Badge, Aside } from '@astrojs/starlight/components';
The Cypress FX2 uses three GPIO ports for hardware control on the SkyWalker-1: Port 0 (IOA), Port 3 (IOD), and Port B (XRAM-mapped IOB). Pin assignments differ significantly between firmware versions due to PCB revisions and design changes. The Cypress FX2 uses three GPIO ports for hardware control on the SkyWalker-1: Port 0 (IOA), Port 3 (IOD), and Port B (XRAM-mapped IOB). Pin assignments differ significantly between firmware versions due to PCB revisions and design changes.
<Aside type="caution" title="Pin Assignments Vary By Firmware"> <Aside type="caution" title="Pin Assignments Vary By Firmware">
The DiSEqC data pin and several LNB control pins changed between firmware versions. Always verify which firmware version is running before driving GPIO pins directly. The DiSEqC data pin and several LNB control pins changed between firmware versions. Always verify which firmware version is running before driving GPIO pins directly.
</Aside> </Aside>
## Port 0 / Port A (SFR 0x80, IOA) ## Port 0 / Port A (SFR 0x80, IOA)
<Tabs> <Tabs>
<TabItem label="Stock Firmware"> <TabItem label="Stock Firmware">
| Pin | v2.06 | Rev.2 v2.10 | v2.13 | Notes | | Pin | v2.06 | Rev.2 v2.10 | v2.13 | Notes |
|-----|-------|-------------|-------|-------| |-----|-------|-------------|-------|-------|
| P0.0 | -- | LNB control (0x97) | **DiSEqC data** | DiSEqC data pin moved across versions | | P0.0 | -- | LNB control (0x97) | **DiSEqC data** | DiSEqC data pin moved across versions |
| P0.1 | Power enable | Power enable | Power enable | BCM4500 power supply enable | | P0.1 | Power enable | Power enable | Power enable | BCM4500 power supply enable |
| P0.2 | Power disable | Power disable (init=0x84) | Power disable | BCM4500 power supply disable | | P0.2 | Power disable | Power disable (init=0x84) | Power disable | BCM4500 power supply disable |
| P0.3 | **22 kHz tone** | **22 kHz tone** | **22 kHz tone** | Gates external 22 kHz oscillator (all versions) | | P0.3 | **22 kHz tone** | **22 kHz tone** | **22 kHz tone** | Gates external 22 kHz oscillator (all versions) |
| P0.4 | **LNB 13V/18V** | **LNB 13V/18V** + DiSEqC data | **LNB 13V/18V** | Also SET_DN_SWITCH bit-bang (all versions) | | P0.4 | **LNB 13V/18V** | **LNB 13V/18V** + DiSEqC data | **LNB 13V/18V** | Also SET_DN_SWITCH bit-bang (all versions) |
| P0.5 | **BCM4500 RESET** | GPIO status input (0x98) | **BCM4500 RESET** | Reset and feedback pin | | P0.5 | **BCM4500 RESET** | GPIO status input (0x98) | **BCM4500 RESET** | Reset and feedback pin |
| P0.6 | -- | GPIO control (0x97) | -- | LNB control on Rev.2 only | | P0.6 | -- | GPIO control (0x97) | -- | LNB control on Rev.2 only |
| P0.7 | **DiSEqC data** | Streaming indicator | Streaming indicator | DiSEqC data on v2.06 only | | P0.7 | **DiSEqC data** | Streaming indicator | Streaming indicator | DiSEqC data on v2.06 only |
</TabItem> </TabItem>
<TabItem label="Custom v3.01.0"> <TabItem label="Custom v3.01.0">
| Pin | Custom v3.01.0 | Notes | | Pin | Custom v3.01.0 | Notes |
|-----|----------------|-------| |-----|----------------|-------|
| P0.0 | -- | Unused | | P0.0 | -- | Unused |
| P0.1 | **Power enable** | BCM4500 power supply enable (HIGH = on) | | P0.1 | **Power enable** | BCM4500 power supply enable (HIGH = on) |
| P0.2 | **Power disable** | BCM4500 power supply disable (LOW = off) | | P0.2 | **Power disable** | BCM4500 power supply disable (LOW = off) |
| P0.3 | **22 kHz tone** | Gates external 22 kHz oscillator | | P0.3 | **22 kHz tone** | Gates external 22 kHz oscillator |
| P0.4 | **LNB 13V/18V** | Voltage select: LOW = 13V, HIGH = 18V | | P0.4 | **LNB 13V/18V** | Voltage select: LOW = 13V, HIGH = 18V |
| P0.5 | **BCM4500 RESET** | LOW = reset asserted, HIGH = released | | P0.5 | **BCM4500 RESET** | LOW = reset asserted, HIGH = released |
| P0.6 | -- | Unused | | P0.6 | -- | Unused |
| P0.7 | **DiSEqC data** + streaming | DiSEqC data (matches v2.06); also streaming indicator | | P0.7 | **DiSEqC data** + streaming | DiSEqC data (matches v2.06); also streaming indicator |
</TabItem> </TabItem>
</Tabs> </Tabs>
## Port 3 / Port D (SFR 0xB0, IOD) ## Port 3 / Port D (SFR 0xB0, IOD)
These pins are consistent across all firmware versions: These pins are consistent across all firmware versions:
| Pin | Function | Active State | Notes | | Pin | Function | Active State | Notes |
|-----|----------|-------------|-------| |-----|----------|-------------|-------|
| P3.0 | Init HIGH | -- | Set during initialization | | P3.0 | Init HIGH | -- | Set during initialization |
| P3.4 | GPIO control | -- | Used by Rev.2 `FUN_CODE_1fcf` | | P3.4 | GPIO control | -- | Used by Rev.2 `FUN_CODE_1fcf` |
| P3.5 | **TS_EN** | LOW | Transport stream enable: LOW = active, HIGH = idle | | P3.5 | **TS_EN** | LOW | Transport stream enable: LOW = active, HIGH = idle |
| P3.6 | **DVB mode** | -- | BCM4500 mode select; DiSEqC port direction (Rev.2) | | P3.6 | **DVB mode** | -- | BCM4500 mode select; DiSEqC port direction (Rev.2) |
| P3.7 | BCM4500 control | HIGH (idle) | De-asserted (HIGH) when streaming stops | | P3.7 | BCM4500 control | HIGH (idle) | De-asserted (HIGH) when streaming stops |
<Aside type="caution" title="P3.5 During Boot"> <Aside type="caution" title="P3.5 During Boot">
P3.5 (TS_EN) must remain HIGH (idle) during the boot sequence and demodulator initialization. Driving it LOW before the BCM4500 is fully initialized may produce undefined behavior on the transport stream bus. P3.5 (TS_EN) must remain HIGH (idle) during the boot sequence and demodulator initialization. Driving it LOW before the BCM4500 is fully initialized may produce undefined behavior on the transport stream bus.
</Aside> </Aside>
## Port B (XRAM-mapped IOB) ## Port B (XRAM-mapped IOB)
Port B is used exclusively by the internal debug commands 0x96--0x98. These commands are not used by the Linux or Windows drivers. Port B is used exclusively by the internal debug commands 0x96--0x98. These commands are not used by the Linux or Windows drivers.
<Tabs> <Tabs>
<TabItem label="v2.06 / v2.13"> <TabItem label="v2.06 / v2.13">
| Pin | Function | Command | | Pin | Function | Command |
|-----|----------|---------| |-----|----------|---------|
| IOB.0 | GPIO status input | GET_GPIO_STATUS (0x98) | | IOB.0 | GPIO status input | GET_GPIO_STATUS (0x98) |
| IOB.1 | LNB control line 1 | SET_GPIO_PINS (0x97) | | IOB.1 | LNB control line 1 | SET_GPIO_PINS (0x97) |
| IOB.2 | LNB control line 2 | SET_GPIO_PINS (0x97) | | IOB.2 | LNB control line 2 | SET_GPIO_PINS (0x97) |
| IOB.3 | LNB GPIO mode | SET_LNB_GPIO_MODE (0x96) | | IOB.3 | LNB GPIO mode | SET_LNB_GPIO_MODE (0x96) |
| IOB.4 | -- | Unused | | IOB.4 | -- | Unused |
</TabItem> </TabItem>
<TabItem label="Rev.2 v2.10"> <TabItem label="Rev.2 v2.10">
| Pin | Function | Command | | Pin | Function | Command |
|-----|----------|---------| |-----|----------|---------|
| IOB.0 | -- | Unused | | IOB.0 | -- | Unused |
| IOB.1 | -- | Unused | | IOB.1 | -- | Unused |
| IOB.2 | -- | Unused | | IOB.2 | -- | Unused |
| IOB.3 | -- | Unused | | IOB.3 | -- | Unused |
| IOB.4 | LNB GPIO mode + control | SET_LNB_GPIO_MODE (0x96) + SET_GPIO_PINS (0x97) | | IOB.4 | LNB GPIO mode + control | SET_LNB_GPIO_MODE (0x96) + SET_GPIO_PINS (0x97) |
Rev.2 moved LNB control from Port B to Port A (P0.6, P0.0). Rev.2 moved LNB control from Port B to Port A (P0.6, P0.0).
</TabItem> </TabItem>
</Tabs> </Tabs>
## DiSEqC Data Pin Summary ## DiSEqC Data Pin Summary
The DiSEqC data pin assignment is the most significant change between firmware versions. The carrier pin (P0.3) remains constant. The DiSEqC data pin assignment is the most significant change between firmware versions. The carrier pin (P0.3) remains constant.
| Firmware Version | Data Pin | Carrier Pin | | Firmware Version | Data Pin | Carrier Pin |
|-----------------|----------|-------------| |-----------------|----------|-------------|
| v2.06 | P0.7 | P0.3 | | v2.06 | P0.7 | P0.3 |
| Rev.2 v2.10 | P0.4 | P0.3 | | Rev.2 v2.10 | P0.4 | P0.3 |
| v2.13 | P0.0 | P0.3 | | v2.13 | P0.0 | P0.3 |
| Custom v3.01.0 | P0.7 | P0.3 | | Custom v3.01.0 | P0.7 | P0.3 |
The data pin is used only internally by the firmware's Manchester encoding logic. It controls whether the 22 kHz carrier gate signal (on P0.3) is cut short or held for the full bit period during DiSEqC transmission. See [DiSEqC Protocol](/lnb-diseqc/diseqc-protocol/) for the encoding details. The data pin is used only internally by the firmware's Manchester encoding logic. It controls whether the 22 kHz carrier gate signal (on P0.3) is cut short or held for the full bit period during DiSEqC transmission. See [DiSEqC Protocol](/lnb-diseqc/diseqc-protocol/) for the encoding details.
## Initial GPIO State ## Initial GPIO State
On power-up, the FX2 initialization code sets: On power-up, the FX2 initialization code sets:
| Register | Value | Decode | | Register | Value | Decode |
|----------|-------|--------| |----------|-------|--------|
| IOA (P0) | 0x84 | P0.7=1 (idle), P0.2=1 (power disable active) | | IOA (P0) | 0x84 | P0.7=1 (idle), P0.2=1 (power disable active) |
| IOD (P3) | 0xE1 | P3.7:5=1 (all control lines idle), P3.0=1 | | IOD (P3) | 0xE1 | P3.7:5=1 (all control lines idle), P3.0=1 |
| OEA | 0xBE | P0.1-5,7 configured as outputs | | OEA | 0xBE | P0.1-5,7 configured as outputs |
These initial states ensure: These initial states ensure:
- The BCM4500 is held in reset (P0.5 driven by output enable, but P0 init has it low after OEA is set) - The BCM4500 is held in reset (P0.5 driven by output enable, but P0 init has it low after OEA is set)
- The transport stream bus is idle (P3.5 = HIGH) - The transport stream bus is idle (P3.5 = HIGH)
- The streaming indicator is off (P0.7 = HIGH) - The streaming indicator is off (P0.7 = HIGH)
- All BCM4500 control lines are de-asserted (P3.7:5 = 1) - All BCM4500 control lines are de-asserted (P3.7:5 = 1)
## Streaming GPIO State Changes ## Streaming GPIO State Changes
| Pin | SFR | Direction | During Streaming | Streaming Stopped | Function | | Pin | SFR | Direction | During Streaming | Streaming Stopped | Function |
|-----|-----|-----------|-----------------|-------------------|----------| |-----|-----|-----------|-----------------|-------------------|----------|
| P0.2 | 0x80 | Output | Set during init | -- | BCM4500 config | | P0.2 | 0x80 | Output | Set during init | -- | BCM4500 config |
| P0.7 | 0x80 | Output | **LOW** | HIGH | Streaming status indicator | | P0.7 | 0x80 | Output | **LOW** | HIGH | Streaming status indicator |
| P3.5 | 0xB0 | Output | Pulsed LOW | HIGH | BCM4500 TS_EN (transport stream enable) | | P3.5 | 0xB0 | Output | Pulsed LOW | HIGH | BCM4500 TS_EN (transport stream enable) |
| P3.6 | 0xB0 | Output | Controlled | HIGH | BCM4500 DVB mode control | | P3.6 | 0xB0 | Output | Controlled | HIGH | BCM4500 DVB mode control |
| P3.7 | 0xB0 | Output | Controlled | HIGH | BCM4500 control line | | P3.7 | 0xB0 | Output | Controlled | HIGH | BCM4500 control line |

View File

@ -1,98 +1,98 @@
--- ---
title: Hardware Overview title: Hardware Overview
description: Board layout, chip identification, supported modulations, and architecture of the Genpix SkyWalker-1 DVB-S USB 2.0 receiver. description: Board layout, chip identification, supported modulations, and architecture of the Genpix SkyWalker-1 DVB-S USB 2.0 receiver.
--- ---
import { Tabs, TabItem, Badge, Aside, CardGrid, Card } from '@astrojs/starlight/components'; import { Tabs, TabItem, Badge, Aside, CardGrid, Card } from '@astrojs/starlight/components';
The Genpix SkyWalker-1 is a standalone USB 2.0 DVB-S satellite receiver built around two primary ICs: a Cypress FX2LP USB microcontroller and a Broadcom BCM4500 satellite demodulator. The FX2 handles all USB communication, LNB control, and DiSEqC signaling, while the BCM4500 performs RF demodulation, forward error correction, and outputs an MPEG-2 transport stream on an 8-bit parallel bus. The Genpix SkyWalker-1 is a standalone USB 2.0 DVB-S satellite receiver built around two primary ICs: a Cypress FX2LP USB microcontroller and a Broadcom BCM4500 satellite demodulator. The FX2 handles all USB communication, LNB control, and DiSEqC signaling, while the BCM4500 performs RF demodulation, forward error correction, and outputs an MPEG-2 transport stream on an 8-bit parallel bus.
<Aside type="tip" title="Get a SkyWalker-1 and support a good cause"> <Aside type="tip" title="Get a SkyWalker-1 and support a good cause">
Genpix Electronics is selling remaining new-in-box SkyWalker-1 units on [eBay](https://www.ebay.com/itm/196142001978), with all net proceeds benefiting the [Leleka Foundation](https://www.leleka.org/) — a charity supporting individuals affected by the conflict in Ukraine. Genpix Electronics is selling remaining new-in-box SkyWalker-1 units on [eBay](https://www.ebay.com/itm/196142001978), with all net proceeds benefiting the [Leleka Foundation](https://www.leleka.org/) — a charity supporting individuals affected by the conflict in Ukraine.
</Aside> </Aside>
## Core Components ## Core Components
| Component | Part Number | Role | | Component | Part Number | Role |
|-----------|-------------|------| |-----------|-------------|------|
| MCU | Cypress CY7C68013A (FX2LP) | USB 2.0 Hi-Speed controller, 8051 core at 48 MHz | | MCU | Cypress CY7C68013A (FX2LP) | USB 2.0 Hi-Speed controller, 8051 core at 48 MHz |
| Demodulator | Broadcom BCM4500 | DVB-S / Turbo / DCII / DSS demodulator, 128-pin MQFP | | Demodulator | Broadcom BCM4500 | DVB-S / Turbo / DCII / DSS demodulator, 128-pin MQFP |
| EEPROM | 24Cxx-family (I2C address 0x51) | FX2 firmware storage, serial number, calibration data | | EEPROM | 24Cxx-family (I2C address 0x51) | FX2 firmware storage, serial number, calibration data |
| Tuner/LNB | Unknown IC (I2C address 0x10) | Tuner or LNB controller on shared I2C bus | | Tuner/LNB | Unknown IC (I2C address 0x10) | Tuner or LNB controller on shared I2C bus |
## Board Block Diagram ## Board Block Diagram
``` ```
+--[ I2C EEPROM 0x51 ] +--[ I2C EEPROM 0x51 ]
| |
USB 2.0 HS | I2C Bus (400 kHz) USB 2.0 HS | I2C Bus (400 kHz)
Host PC <----> [ CY7C68013A FX2LP ] <-----> [ BCM4500 Demod 0x08 ] Host PC <----> [ CY7C68013A FX2LP ] <-----> [ BCM4500 Demod 0x08 ]
| 8051 @ 48 MHz | | | 8051 @ 48 MHz | |
| GPIF Engine |<-----------+ 8-bit parallel TS | GPIF Engine |<-----------+ 8-bit parallel TS
| EP2 Bulk IN | | EP2 Bulk IN |
| GPIO (P0/P3) |---> [ 22 kHz Osc ] ---> LNB/Coax | GPIO (P0/P3) |---> [ 22 kHz Osc ] ---> LNB/Coax
| |---> [ LNB Voltage Ctrl ] | |---> [ LNB Voltage Ctrl ]
+-----------------+ +-----------------+
| |
+--[ Tuner/LNB IC 0x10 ] +--[ Tuner/LNB IC 0x10 ]
``` ```
The GPIF engine inside the FX2 transfers the BCM4500's transport stream output directly into USB bulk endpoint EP2 with zero firmware intervention in the data path. This hardware-managed pipeline provides approximately 5x bandwidth headroom over the maximum DVB-S transport stream rate. The GPIF engine inside the FX2 transfers the BCM4500's transport stream output directly into USB bulk endpoint EP2 with zero firmware intervention in the data path. This hardware-managed pipeline provides approximately 5x bandwidth headroom over the maximum DVB-S transport stream rate.
## Supported Modulations ## Supported Modulations
| Index | Modulation | Constant | FEC Family | | Index | Modulation | Constant | FEC Family |
|-------|-----------|----------|------------| |-------|-----------|----------|------------|
| 0 | DVB-S QPSK <Badge text="Standard" variant="note" /> | `ADV_MOD_DVB_QPSK` | Viterbi + Reed-Solomon | | 0 | DVB-S QPSK <Badge text="Standard" variant="note" /> | `ADV_MOD_DVB_QPSK` | Viterbi + Reed-Solomon |
| 1 | Turbo-coded QPSK <Badge text="Turbo" variant="success" /> | `ADV_MOD_TURBO_QPSK` | Turbo | | 1 | Turbo-coded QPSK <Badge text="Turbo" variant="success" /> | `ADV_MOD_TURBO_QPSK` | Turbo |
| 2 | Turbo-coded 8PSK <Badge text="Turbo" variant="success" /> | `ADV_MOD_TURBO_8PSK` | Turbo | | 2 | Turbo-coded 8PSK <Badge text="Turbo" variant="success" /> | `ADV_MOD_TURBO_8PSK` | Turbo |
| 3 | Turbo-coded 16QAM <Badge text="Turbo" variant="success" /> | `ADV_MOD_TURBO_16QAM` | Turbo | | 3 | Turbo-coded 16QAM <Badge text="Turbo" variant="success" /> | `ADV_MOD_TURBO_16QAM` | Turbo |
| 4 | Digicipher II Combo <Badge text="DCII" variant="caution" /> | `ADV_MOD_DCII_C_QPSK` | DCII | | 4 | Digicipher II Combo <Badge text="DCII" variant="caution" /> | `ADV_MOD_DCII_C_QPSK` | DCII |
| 5 | Digicipher II I-stream (split) <Badge text="DCII" variant="caution" /> | `ADV_MOD_DCII_I_QPSK` | DCII | | 5 | Digicipher II I-stream (split) <Badge text="DCII" variant="caution" /> | `ADV_MOD_DCII_I_QPSK` | DCII |
| 6 | Digicipher II Q-stream (split) <Badge text="DCII" variant="caution" /> | `ADV_MOD_DCII_Q_QPSK` | DCII | | 6 | Digicipher II Q-stream (split) <Badge text="DCII" variant="caution" /> | `ADV_MOD_DCII_Q_QPSK` | DCII |
| 7 | Digicipher II Offset QPSK <Badge text="DCII" variant="caution" /> | `ADV_MOD_DCII_C_OQPSK` | DCII | | 7 | Digicipher II Offset QPSK <Badge text="DCII" variant="caution" /> | `ADV_MOD_DCII_C_OQPSK` | DCII |
| 8 | DSS QPSK <Badge text="DSS" variant="note" /> | `ADV_MOD_DSS_QPSK` | Viterbi + Reed-Solomon | | 8 | DSS QPSK <Badge text="DSS" variant="note" /> | `ADV_MOD_DSS_QPSK` | Viterbi + Reed-Solomon |
| 9 | DVB-S BPSK <Badge text="Standard" variant="note" /> | `ADV_MOD_DVB_BPSK` | Viterbi + Reed-Solomon | | 9 | DVB-S BPSK <Badge text="Standard" variant="note" /> | `ADV_MOD_DVB_BPSK` | Viterbi + Reed-Solomon |
<Aside type="caution" title="DVB-S2 Not Supported"> <Aside type="caution" title="DVB-S2 Not Supported">
DVB-S2 is **not** supported by the SkyWalker-1. This is a fundamental hardware limitation of the BCM4500 demodulator silicon -- it was designed before the DVB-S2 standard was ratified (March 2005) and contains no LDPC or BCH decoder hardware. No firmware update can add DVB-S2 support. See the [DVB-S2 Incompatibility](/driver/dvb-s2/) page for the full technical analysis. DVB-S2 is **not** supported by the SkyWalker-1. This is a fundamental hardware limitation of the BCM4500 demodulator silicon -- it was designed before the DVB-S2 standard was ratified (March 2005) and contains no LDPC or BCH decoder hardware. No firmware update can add DVB-S2 support. See the [DVB-S2 Incompatibility](/driver/dvb-s2/) page for the full technical analysis.
</Aside> </Aside>
## Architecture Overview ## Architecture Overview
<CardGrid> <CardGrid>
<Card title="USB Interface" icon="laptop"> <Card title="USB Interface" icon="laptop">
EP0 for vendor commands (tuning, LNB control, status). EP2 for bulk MPEG-2 transport stream data. VID `0x09C0`, PID `0x0203`. See [USB Interface](/usb/interface/). EP0 for vendor commands (tuning, LNB control, status). EP2 for bulk MPEG-2 transport stream data. VID `0x09C0`, PID `0x0203`. See [USB Interface](/usb/interface/).
</Card> </Card>
<Card title="BCM4500 Demodulator" icon="seti:config"> <Card title="BCM4500 Demodulator" icon="seti:config">
Indirect register access via I2C (0xA6/0xA7/0xA8 protocol). Two FEC decoder paths: turbo codes and legacy Viterbi/Reed-Solomon. See [Demodulator Interface](/bcm4500/demodulator/). Indirect register access via I2C (0xA6/0xA7/0xA8 protocol). Two FEC decoder paths: turbo codes and legacy Viterbi/Reed-Solomon. See [Demodulator Interface](/bcm4500/demodulator/).
</Card> </Card>
<Card title="GPIF Streaming" icon="right-arrow"> <Card title="GPIF Streaming" icon="right-arrow">
Hardware-managed data path. 8-bit parallel bus from BCM4500 to EP2 FIFO via GPIF master read. AUTOIN auto-commits full packets to USB. See [GPIF Streaming](/bcm4500/gpif-streaming/). Hardware-managed data path. 8-bit parallel bus from BCM4500 to EP2 FIFO via GPIF master read. AUTOIN auto-commits full packets to USB. See [GPIF Streaming](/bcm4500/gpif-streaming/).
</Card> </Card>
<Card title="I2C Bus" icon="setting"> <Card title="I2C Bus" icon="setting">
400 kHz bus connecting FX2 to BCM4500 (0x08), tuner IC (0x10), and EEPROM (0x51). Bit-banged DiSEqC on separate GPIO pins. See [I2C Bus Architecture](/i2c/bus-architecture/). 400 kHz bus connecting FX2 to BCM4500 (0x08), tuner IC (0x10), and EEPROM (0x51). Bit-banged DiSEqC on separate GPIO pins. See [I2C Bus Architecture](/i2c/bus-architecture/).
</Card> </Card>
</CardGrid> </CardGrid>
## FEC Architecture ## FEC Architecture
The BCM4500 contains two distinct FEC decoder paths: The BCM4500 contains two distinct FEC decoder paths:
1. **Advanced Modulation Turbo FEC Decoder** -- Iterative turbo code decoder supporting QPSK (rates 1/4, 1/2, 3/4), 8PSK (rates 2/3, 3/4, 5/6, 8/9), 16QAM (rate 3/4), with Reed-Solomon (t=10) outer code. 1. **Advanced Modulation Turbo FEC Decoder** -- Iterative turbo code decoder supporting QPSK (rates 1/4, 1/2, 3/4), 8PSK (rates 2/3, 3/4, 5/6, 8/9), 16QAM (rate 3/4), with Reed-Solomon (t=10) outer code.
2. **Legacy DVB/DIRECTV/DCII-Compliant FEC Decoder** -- Concatenated Viterbi inner decoder (convolutional code, rates 1/2 through 7/8) plus Reed-Solomon outer decoder. 2. **Legacy DVB/DIRECTV/DCII-Compliant FEC Decoder** -- Concatenated Viterbi inner decoder (convolutional code, rates 1/2 through 7/8) plus Reed-Solomon outer decoder.
There is no LDPC or BCH decoder hardware. The turbo FEC codes are Broadcom/EchoStar proprietary and are not part of any open standard. There is no LDPC or BCH decoder hardware. The turbo FEC codes are Broadcom/EchoStar proprietary and are not part of any open standard.
## Firmware ## Firmware
The SkyWalker-1 boots from an on-board I2C EEPROM containing firmware in Cypress C2 format. No host-side firmware files are required. Multiple stock firmware versions have been identified: The SkyWalker-1 boots from an on-board I2C EEPROM containing firmware in Cypress C2 format. No host-side firmware files are required. Multiple stock firmware versions have been identified:
| Firmware | Version ID | Build Date | Notes | | Firmware | Version ID | Build Date | Notes |
|----------|-----------|------------|-------| |----------|-----------|------------|-------|
| v2.06.04 | 0x020604 | 2007-07-13 | Original release, 61 functions | | v2.06.04 | 0x020604 | 2007-07-13 | Original release, 61 functions |
| v2.13.01 | 0x020D01 | 2010-03-12 | Latest revision, 82-88 functions | | v2.13.01 | 0x020D01 | 2010-03-12 | Latest revision, 82-88 functions |
| Custom v3.01.0 | 0x030100 | 2026-02-12 | Open-source SDCC + fx2lib, RAM-loaded | | Custom v3.01.0 | 0x030100 | 2026-02-12 | Open-source SDCC + fx2lib, RAM-loaded |
See [Firmware Version Comparison](/firmware/version-comparison/) for a full analysis of the differences between stock firmware versions. See [Firmware Version Comparison](/firmware/version-comparison/) for a full analysis of the differences between stock firmware versions.

View File

@ -1,110 +1,110 @@
--- ---
title: RF Coverage and Limitations title: RF Coverage and Limitations
description: How LNB frequency shifting maps the 950-2150 MHz IF range to different RF bands, and what the hardware can and cannot do beyond satellite reception. description: How LNB frequency shifting maps the 950-2150 MHz IF range to different RF bands, and what the hardware can and cannot do beyond satellite reception.
--- ---
import { Aside } from '@astrojs/starlight/components'; import { Aside } from '@astrojs/starlight/components';
The SkyWalker-1 was designed as a DVB-S satellite receiver, but the BCM4500's signal monitoring registers work whether or not a signal is locked. This makes the hardware useful as a crude spectrum analyzer and RF power detector across any band an LNB can translate into the 950--2150 MHz IF window. Understanding what the hardware actually measures -- and where the measurement breaks down -- is essential to interpreting sweep results correctly. The SkyWalker-1 was designed as a DVB-S satellite receiver, but the BCM4500's signal monitoring registers work whether or not a signal is locked. This makes the hardware useful as a crude spectrum analyzer and RF power detector across any band an LNB can translate into the 950--2150 MHz IF window. Understanding what the hardware actually measures -- and where the measurement breaks down -- is essential to interpreting sweep results correctly.
## How the Power Detector Works ## How the Power Detector Works
The BCM4500 demodulator contains an AGC (Automatic Gain Control) loop that adjusts the tuner gain to maintain a constant signal level at the ADC. The AGC register values (indirect registers 0x02--0x05) reflect how much gain the system is applying. This mechanism operates continuously, regardless of whether the demodulator achieves signal lock. The BCM4500 demodulator contains an AGC (Automatic Gain Control) loop that adjusts the tuner gain to maintain a constant signal level at the ADC. The AGC register values (indirect registers 0x02--0x05) reflect how much gain the system is applying. This mechanism operates continuously, regardless of whether the demodulator achieves signal lock.
The key insight: **higher AGC values mean weaker signals** (the system needs more gain to reach the target level). The AGC responds to the total received power within the tuner's passband at the tuned frequency. It does not discriminate between modulated carriers, noise floors, or interference -- it measures raw RF energy. The key insight: **higher AGC values mean weaker signals** (the system needs more gain to reach the target level). The AGC responds to the total received power within the tuner's passband at the tuned frequency. It does not discriminate between modulated carriers, noise floors, or interference -- it measures raw RF energy.
The SIGNAL_MONITOR command (0xB7) reads both the SNR and AGC registers in a single USB transfer, avoiding the round-trip overhead of separate indirect register reads. The TUNE_MONITOR command (0xB8) combines tune + settle + read into one operation, forming the building block for spectrum sweeps. See [Signal Monitoring](/bcm4500/signal-monitoring/) for the register-level details. The SIGNAL_MONITOR command (0xB7) reads both the SNR and AGC registers in a single USB transfer, avoiding the round-trip overhead of separate indirect register reads. The TUNE_MONITOR command (0xB8) combines tune + settle + read into one operation, forming the building block for spectrum sweeps. See [Signal Monitoring](/bcm4500/signal-monitoring/) for the register-level details.
## LNB Frequency Shifting ## LNB Frequency Shifting
A Low-Noise Block downconverter (LNB) mounted at the dish feed performs frequency translation: it mixes the incoming RF signal with its internal local oscillator (LO), producing an intermediate frequency (IF) output that travels down the coaxial cable to the receiver. A Low-Noise Block downconverter (LNB) mounted at the dish feed performs frequency translation: it mixes the incoming RF signal with its internal local oscillator (LO), producing an intermediate frequency (IF) output that travels down the coaxial cable to the receiver.
``` ```
actual_rf = if_frequency + lnb_lo actual_rf = if_frequency + lnb_lo
if_frequency = actual_rf - lnb_lo if_frequency = actual_rf - lnb_lo
``` ```
The SkyWalker-1 tunes within a fixed IF range: 950--2150 MHz. The actual RF band covered depends entirely on which LNB is connected and what its LO frequency is. The receiver has no knowledge of the LNB's LO -- the host software must account for the frequency offset when computing tune parameters and interpreting results. The SkyWalker-1 tunes within a fixed IF range: 950--2150 MHz. The actual RF band covered depends entirely on which LNB is connected and what its LO frequency is. The receiver has no knowledge of the LNB's LO -- the host software must account for the frequency offset when computing tune parameters and interpreting results.
## RF Coverage Map ## RF Coverage Map
| Configuration | LNB LO (MHz) | IF Range (MHz) | Actual RF Covered (MHz) | Typical Use | | Configuration | LNB LO (MHz) | IF Range (MHz) | Actual RF Covered (MHz) | Typical Use |
|---|---|---|---|---| |---|---|---|---|---|
| Ku-band low | 9,750 | 950--2,150 | 10,700--11,900 | Satellite TV low band | | Ku-band low | 9,750 | 950--2,150 | 10,700--11,900 | Satellite TV low band |
| Ku-band high | 10,600 | 950--2,150 | 11,550--12,750 | Satellite TV high band | | Ku-band high | 10,600 | 950--2,150 | 11,550--12,750 | Satellite TV high band |
| C-band | 5,150 | 950--2,150 | 6,100--7,300 | C-band satellite | | C-band | 5,150 | 950--2,150 | 6,100--7,300 | C-band satellite |
| No LNB (direct) | 0 | 950--2,150 | 950--2,150 | L-band direct input | | No LNB (direct) | 0 | 950--2,150 | 950--2,150 | L-band direct input |
| Custom (9.0 GHz) | 9,000 | 950--2,150 | 9,950--11,150 | QO-100 DATV | | Custom (9.0 GHz) | 9,000 | 950--2,150 | 9,950--11,150 | QO-100 DATV |
<Aside type="note" title="Universal LNB Band Switching"> <Aside type="note" title="Universal LNB Band Switching">
Universal Ku-band LNBs switch between low (9,750 MHz) and high (10,600 MHz) LO frequencies using the 22 kHz tone signal. The SkyWalker-1 controls this tone via GPIO P0.3 -- see [LNB Control](/lnb-diseqc/lnb-control/) for the command interface. The `tune.py` tool handles band switching automatically via the `--band low/high` option. Universal Ku-band LNBs switch between low (9,750 MHz) and high (10,600 MHz) LO frequencies using the 22 kHz tone signal. The SkyWalker-1 controls this tone via GPIO P0.3 -- see [LNB Control](/lnb-diseqc/lnb-control/) for the command interface. The `tune.py` tool handles band switching automatically via the `--band low/high` option.
</Aside> </Aside>
## L-Band Direct Input ## L-Band Direct Input
With no LNB -- cable connected directly to an antenna or feed -- the hardware covers the raw 950--2,150 MHz IF range. This encompasses several interesting allocations: With no LNB -- cable connected directly to an antenna or feed -- the hardware covers the raw 950--2,150 MHz IF range. This encompasses several interesting allocations:
| Range (MHz) | Allocation | Detectable? | Demodulatable? | | Range (MHz) | Allocation | Detectable? | Demodulatable? |
|---|---|---|---| |---|---|---|---|
| 1,240--1,300 | Amateur 23 cm band | Yes (energy) | No (SSB/CW/FM) | | 1,240--1,300 | Amateur 23 cm band | Yes (energy) | No (SSB/CW/FM) |
| 1,525--1,559 | Inmarsat downlink | Yes (energy) | No (proprietary) | | 1,525--1,559 | Inmarsat downlink | Yes (energy) | No (proprietary) |
| 1,559--1,610 | GNSS (GPS L1, Galileo E1) | Yes (spread spectrum) | No (CDMA/BOC) | | 1,559--1,610 | GNSS (GPS L1, Galileo E1) | Yes (spread spectrum) | No (CDMA/BOC) |
| 1,610--1,626 | Iridium downlink | Yes (energy) | No (TDMA/FDMA) | | 1,610--1,626 | Iridium downlink | Yes (energy) | No (TDMA/FDMA) |
| 1,670--1,710 | MetSat (GOES LRIT, NOAA HRPT) | Yes (carrier) | No (non-DVB framing) | | 1,670--1,710 | MetSat (GOES LRIT, NOAA HRPT) | Yes (carrier) | No (non-DVB framing) |
| 1,710--1,785 | LTE/AWS uplink | Yes (energy) | No (OFDM) | | 1,710--1,785 | LTE/AWS uplink | Yes (energy) | No (OFDM) |
| 1,920--2,025 | UMTS uplink | Yes (energy) | No (WCDMA) | | 1,920--2,025 | UMTS uplink | Yes (energy) | No (WCDMA) |
"Detectable" means the AGC registers respond to RF energy at that frequency -- the hardware sees something. "Demodulatable" means the BCM4500 can lock onto the signal and produce a decoded transport stream. Only DVB-S, Turbo-coded, DCII, and DSS signals can be demodulated. Everything else shows up as an energy level without any ability to extract data. "Detectable" means the AGC registers respond to RF energy at that frequency -- the hardware sees something. "Demodulatable" means the BCM4500 can lock onto the signal and produce a decoded transport stream. Only DVB-S, Turbo-coded, DCII, and DSS signals can be demodulated. Everything else shows up as an energy level without any ability to extract data.
### The QO-100 Exception ### The QO-100 Exception
The Es'hail-2/QO-100 amateur satellite at 25.9 degrees East carries DVB-S DATV signals in the 10,491--10,499 MHz range. These are actual DVB-S QPSK signals at low symbol rates (333--2,000 ksps) -- the one case where amateur satellite signals use a modulation the SkyWalker-1 can natively demodulate. The Es'hail-2/QO-100 amateur satellite at 25.9 degrees East carries DVB-S DATV signals in the 10,491--10,499 MHz range. These are actual DVB-S QPSK signals at low symbol rates (333--2,000 ksps) -- the one case where amateur satellite signals use a modulation the SkyWalker-1 can natively demodulate.
The problem is IF range. With a standard 9,750 MHz universal LNB, 10,494 MHz maps to 744 MHz IF -- below the SkyWalker-1's 950 MHz minimum. A custom LNB with a ~9.0 GHz local oscillator puts the same signal at ~1,494 MHz IF, comfortably in range. The problem is IF range. With a standard 9,750 MHz universal LNB, 10,494 MHz maps to 744 MHz IF -- below the SkyWalker-1's 950 MHz minimum. A custom LNB with a ~9.0 GHz local oscillator puts the same signal at ~1,494 MHz IF, comfortably in range.
<Aside type="caution" title="Symbol Rate Floor"> <Aside type="caution" title="Symbol Rate Floor">
The minimum symbol rate the BCM4500 supports is 256 ksps. Some QO-100 DATV signals run as low as 333 ksps, which is within range but near the lower boundary. Lock acquisition at these rates may require longer settling times. The minimum symbol rate the BCM4500 supports is 256 ksps. Some QO-100 DATV signals run as low as 333 ksps, which is within range but near the lower boundary. Lock acquisition at these rates may require longer settling times.
</Aside> </Aside>
## Hardware Limitations ## Hardware Limitations
The SkyWalker-1 is a satellite receiver repurposed as a measurement tool. The results are useful but carry inherent constraints worth understanding before interpreting sweep data. The SkyWalker-1 is a satellite receiver repurposed as a measurement tool. The results are useful but carry inherent constraints worth understanding before interpreting sweep data.
### Resolution Bandwidth ### Resolution Bandwidth
The minimum symbol rate is 256 ksps, giving a minimum resolution bandwidth of approximately 346 kHz (`symbol_rate * 1.35` roll-off factor). This is far coarser than a dedicated spectrum analyzer, which might offer 1 kHz or even 10 Hz RBW. Narrowband signals -- SSB at 3 kHz, CW at 500 Hz, FM repeater outputs at 25 kHz -- cannot be individually resolved. They appear as a single energy bump within the ~346 kHz measurement window, indistinguishable from each other or from broadband noise at similar levels. The minimum symbol rate is 256 ksps, giving a minimum resolution bandwidth of approximately 346 kHz (`symbol_rate * 1.35` roll-off factor). This is far coarser than a dedicated spectrum analyzer, which might offer 1 kHz or even 10 Hz RBW. Narrowband signals -- SSB at 3 kHz, CW at 500 Hz, FM repeater outputs at 25 kHz -- cannot be individually resolved. They appear as a single energy bump within the ~346 kHz measurement window, indistinguishable from each other or from broadband noise at similar levels.
### Dynamic Range ### Dynamic Range
The AGC provides approximately 30--40 dB of usable dynamic range. A professional spectrum analyzer offers 70+ dB. The practical consequence: weak signals near strong ones get masked. A satellite transponder 25 dB above the noise floor is clearly visible; a signal 5 dB above the noise floor next to a strong adjacent carrier may not be. The AGC provides approximately 30--40 dB of usable dynamic range. A professional spectrum analyzer offers 70+ dB. The practical consequence: weak signals near strong ones get masked. A satellite transponder 25 dB above the noise floor is clearly visible; a signal 5 dB above the noise floor next to a strong adjacent carrier may not be.
### Sweep Speed ### Sweep Speed
Each tune-measure step takes approximately 12 ms (tune settling + dwell + USB transfer). A full 950--2,150 MHz sweep at 5 MHz steps requires about 240 steps at 12 ms each, totaling approximately 2.9 seconds. This is adequate for mapping satellite transponders or identifying persistent carriers, but too slow for capturing transient signals or frequency-hopping transmissions. Each tune-measure step takes approximately 12 ms (tune settling + dwell + USB transfer). A full 950--2,150 MHz sweep at 5 MHz steps requires about 240 steps at 12 ms each, totaling approximately 2.9 seconds. This is adequate for mapping satellite transponders or identifying persistent carriers, but too slow for capturing transient signals or frequency-hopping transmissions.
### What It Does Well ### What It Does Well
| Strength | Detail | | Strength | Detail |
|---|---| |---|---|
| Built-in LNB power | 13V/18V, 22 kHz tone, DiSEqC 1.0/1.2 -- complete satellite receiver chain with no external hardware | | Built-in LNB power | 13V/18V, 22 kHz tone, DiSEqC 1.0/1.2 -- complete satellite receiver chain with no external hardware |
| Native DVB-S demodulation | Can lock, decode, and stream DVB-S, Turbo, DCII, and DSS signals as MPEG-2 transport streams | | Native DVB-S demodulation | Can lock, decode, and stream DVB-S, Turbo, DCII, and DSS signals as MPEG-2 transport streams |
| Power measurement | Detects RF energy across the full 950--2,150 MHz IF range regardless of modulation | | Power measurement | Detects RF energy across the full 950--2,150 MHz IF range regardless of modulation |
| Transport stream capture | GPIF streaming provides real MPEG-2 TS data for locked signals | | Transport stream capture | GPIF streaming provides real MPEG-2 TS data for locked signals |
| Low cost | Repurposes existing satellite receiver hardware for spectrum awareness | | Low cost | Repurposes existing satellite receiver hardware for spectrum awareness |
### What It Cannot Do ### What It Cannot Do
| Limitation | Detail | | Limitation | Detail |
|---|---| |---|---|
| Not an SDR | Cannot capture raw IQ samples or demodulate arbitrary waveforms | | Not an SDR | Cannot capture raw IQ samples or demodulate arbitrary waveforms |
| Fixed demod pipeline | Only DVB-S / Turbo / DCII / DSS modulations -- no FM, SSB, CW, OFDM, ATSC | | Fixed demod pipeline | Only DVB-S / Turbo / DCII / DSS modulations -- no FM, SSB, CW, OFDM, ATSC |
| Coarse RBW | Minimum ~346 kHz resolution bandwidth; narrowband signals are unresolvable | | Coarse RBW | Minimum ~346 kHz resolution bandwidth; narrowband signals are unresolvable |
| Limited dynamic range | ~30--40 dB usable vs 70+ dB for dedicated spectrum analyzers | | Limited dynamic range | ~30--40 dB usable vs 70+ dB for dedicated spectrum analyzers |
| No DVB-S2 | Incompatible FEC (LDPC vs Reed-Solomon) -- see [DVB-S2 Incompatibility](/driver/dvb-s2/) | | No DVB-S2 | Incompatible FEC (LDPC vs Reed-Solomon) -- see [DVB-S2 Incompatibility](/driver/dvb-s2/) |
## See Also ## See Also
- [Tuning Tool](/tools/tuning/) -- the primary user-facing tool for tuning, monitoring, and capture - [Tuning Tool](/tools/tuning/) -- the primary user-facing tool for tuning, monitoring, and capture
- [RF Specifications](/hardware/rf-specifications/) -- electrical parameters, signal path, and LNB current limits - [RF Specifications](/hardware/rf-specifications/) -- electrical parameters, signal path, and LNB current limits
- [Signal Monitoring](/bcm4500/signal-monitoring/) -- AGC and SNR register details used by the power detector - [Signal Monitoring](/bcm4500/signal-monitoring/) -- AGC and SNR register details used by the power detector
- [LNB Control](/lnb-diseqc/lnb-control/) -- voltage, tone, and DiSEqC command interface - [LNB Control](/lnb-diseqc/lnb-control/) -- voltage, tone, and DiSEqC command interface

View File

@ -1,94 +1,94 @@
--- ---
title: RF Specifications title: RF Specifications
description: RF input parameters, LNB voltage and current limits, and symbol rate range for the SkyWalker-1. description: RF input parameters, LNB voltage and current limits, and symbol rate range for the SkyWalker-1.
--- ---
import { Aside } from '@astrojs/starlight/components'; import { Aside } from '@astrojs/starlight/components';
## RF Input Parameters ## RF Input Parameters
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| IF frequency range | 950 -- 2150 MHz | | IF frequency range | 950 -- 2150 MHz |
| Symbol rate | 256 Ksps -- 30 Msps | | Symbol rate | 256 Ksps -- 30 Msps |
| Input connector | IEC F-type female | | Input connector | IEC F-type female |
The IF frequency is the intermediate frequency after LNB downconversion. The host computes it as `(RF_freq - LO_freq) * multiplier` and sends it in the [TUNE_8PSK](/bcm4500/tuning-protocol/) command payload. The IF frequency is the intermediate frequency after LNB downconversion. The host computes it as `(RF_freq - LO_freq) * multiplier` and sends it in the [TUNE_8PSK](/bcm4500/tuning-protocol/) command payload.
## LNB Power Supply ## LNB Power Supply
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| LNB voltage (standard) | 13V / 18V | | LNB voltage (standard) | 13V / 18V |
| LNB voltage (boosted) | 14V / 19V (with USE_EXTRA_VOLT) | | LNB voltage (boosted) | 14V / 19V (with USE_EXTRA_VOLT) |
| Maximum continuous current | 450 mA | | Maximum continuous current | 450 mA |
| Maximum burst current | 750 mA | | Maximum burst current | 750 mA |
<Aside type="caution" title="Current Limits"> <Aside type="caution" title="Current Limits">
750 mA is the maximum **non-continuous** (several minutes) allowable load. To avoid overheating the on-board voltage regulator, do not exceed **450 mA** for permanent load. Exceeding these limits may damage the SkyWalker-1 hardware. 750 mA is the maximum **non-continuous** (several minutes) allowable load. To avoid overheating the on-board voltage regulator, do not exceed **450 mA** for permanent load. Exceeding these limits may damage the SkyWalker-1 hardware.
</Aside> </Aside>
LNB voltage is controlled via GPIO P0.4 on all firmware versions. The voltage selection determines the polarization: LNB voltage is controlled via GPIO P0.4 on all firmware versions. The voltage selection determines the polarization:
| wValue | Voltage | GPIO P0.4 | Polarization | | wValue | Voltage | GPIO P0.4 | Polarization |
|--------|---------|-----------|-------------| |--------|---------|-----------|-------------|
| 0 | 13V | LOW | Vertical / Circular-Right | | 0 | 13V | LOW | Vertical / Circular-Right |
| 1 | 18V | HIGH | Horizontal / Circular-Left | | 1 | 18V | HIGH | Horizontal / Circular-Left |
The USE_EXTRA_VOLT command (0x94) enables a +1V boost for long cable runs by toggling bit 3 of the LNB control register at XRAM 0xE0B6 (0x62 = normal, 0x6A = boosted). See [Vendor Commands](/usb/vendor-commands/) for the command interface. The USE_EXTRA_VOLT command (0x94) enables a +1V boost for long cable runs by toggling bit 3 of the LNB control register at XRAM 0xE0B6 (0x62 = normal, 0x6A = boosted). See [Vendor Commands](/usb/vendor-commands/) for the command interface.
## Switch Control ## Switch Control
The SkyWalker-1 supports multiple satellite switching protocols: The SkyWalker-1 supports multiple satellite switching protocols:
| Protocol | Implementation | Command | | Protocol | Implementation | Command |
|----------|---------------|---------| |----------|---------------|---------|
| 22 kHz tone | GPIO P0.3 gates external oscillator | SET_22KHZ_TONE (0x8C) | | 22 kHz tone | GPIO P0.3 gates external oscillator | SET_22KHZ_TONE (0x8C) |
| Tone Burst (mini DiSEqC) | Timer2-based carrier gating | SEND_DISEQC_COMMAND (0x8D) | | Tone Burst (mini DiSEqC) | Timer2-based carrier gating | SEND_DISEQC_COMMAND (0x8D) |
| DiSEqC 1.0 | Timer2 Manchester encoding | SEND_DISEQC_COMMAND (0x8D) | | DiSEqC 1.0 | Timer2 Manchester encoding | SEND_DISEQC_COMMAND (0x8D) |
| DiSEqC 1.2 | Timer2 Manchester encoding | SEND_DISEQC_COMMAND (0x8D) | | DiSEqC 1.2 | Timer2 Manchester encoding | SEND_DISEQC_COMMAND (0x8D) |
| Legacy Dish Network | 7-bit serial bit-bang on P0.4 | SET_DN_SWITCH (0x8F) | | Legacy Dish Network | 7-bit serial bit-bang on P0.4 | SET_DN_SWITCH (0x8F) |
## 22 kHz Tone ## 22 kHz Tone
The 22 kHz tone signal is generated by an external oscillator on the PCB, gated by GPIO P0.3. The firmware does not generate the 22 kHz carrier directly -- it only enables or disables the oscillator output. The 22 kHz tone signal is generated by an external oscillator on the PCB, gated by GPIO P0.3. The firmware does not generate the 22 kHz carrier directly -- it only enables or disables the oscillator output.
| wValue | State | GPIO P0.3 | Band Selection | | wValue | State | GPIO P0.3 | Band Selection |
|--------|-------|-----------|------| |--------|-------|-----------|------|
| 0 | OFF | LOW | Low band (9.75 GHz LO on universal LNB) | | 0 | OFF | LOW | Low band (9.75 GHz LO on universal LNB) |
| 1 | ON | HIGH | High band (10.6 GHz LO on universal LNB) | | 1 | ON | HIGH | High band (10.6 GHz LO on universal LNB) |
## Signal Path ## Signal Path
``` ```
Satellite Satellite
| |
v v
[ LNB on Dish ] <-- 13V/18V + 22kHz from SkyWalker-1 [ LNB on Dish ] <-- 13V/18V + 22kHz from SkyWalker-1
| |
| Coax (950-2150 MHz IF) | Coax (950-2150 MHz IF)
v v
[ SkyWalker-1 F-connector ] [ SkyWalker-1 F-connector ]
| |
v v
[ BCM4500 Demodulator ] -- demod + FEC decode [ BCM4500 Demodulator ] -- demod + FEC decode
| |
| 8-bit parallel MPEG-2 TS | 8-bit parallel MPEG-2 TS
v v
[ FX2 GPIF Engine ] -- zero-copy DMA to EP2 [ FX2 GPIF Engine ] -- zero-copy DMA to EP2
| |
| USB 2.0 High-Speed Bulk | USB 2.0 High-Speed Bulk
v v
[ Host PC ] [ Host PC ]
``` ```
The USB/GPIF data path has substantial headroom over the satellite link throughput: The USB/GPIF data path has substantial headroom over the satellite link throughput:
| Metric | Value | | Metric | Value |
|--------|-------| |--------|-------|
| USB 2.0 HS bulk (practical) | ~280 Mbps (~35 MB/s) | | USB 2.0 HS bulk (practical) | ~280 Mbps (~35 MB/s) |
| GPIF engine (theoretical) | 48 MHz x 8 bits = 384 Mbps | | GPIF engine (theoretical) | 48 MHz x 8 bits = 384 Mbps |
| Typical DVB-S TS rate | 1--5 MB/s | | Typical DVB-S TS rate | 1--5 MB/s |
| Maximum symbol rate (30 Msps) | ~58 Mbps | | Maximum symbol rate (30 Msps) | ~58 Mbps |
The bottleneck for all supported modulation modes is the satellite link, not the USB data path. The bottleneck for all supported modulation modes is the satellite link, not the USB data path.

View File

@ -1,156 +1,156 @@
--- ---
title: I2C Bus Architecture title: I2C Bus Architecture
description: FX2 I2C controller details, bus topology, device addresses, and the combined write-read protocol. description: FX2 I2C controller details, bus topology, device addresses, and the combined write-read protocol.
--- ---
import { Aside, Steps } from '@astrojs/starlight/components'; import { Aside, Steps } from '@astrojs/starlight/components';
The SkyWalker-1 uses a single I2C bus connecting the FX2 microcontroller (master) to three slave devices. The FX2's hardware I2C controller handles all bus transactions through XRAM-mapped registers. The SkyWalker-1 uses a single I2C bus connecting the FX2 microcontroller (master) to three slave devices. The FX2's hardware I2C controller handles all bus transactions through XRAM-mapped registers.
## FX2 I2C Controller ## FX2 I2C Controller
| SFR | Address | Function | | SFR | Address | Function |
|-----|---------|----------| |-----|---------|----------|
| I2CS | 0xE678 (XRAM) | I2C control/status register | | I2CS | 0xE678 (XRAM) | I2C control/status register |
| I2DAT | 0xE679 (XRAM) | I2C data register | | I2DAT | 0xE679 (XRAM) | I2C data register |
| I2CTL | 0xE67A (XRAM) | I2C control (speed selection) | | I2CTL | 0xE67A (XRAM) | I2C control (speed selection) |
### I2CS Control/Status Bits ### I2CS Control/Status Bits
| Bit | Name | Function | | Bit | Name | Function |
|-----|------|----------| |-----|------|----------|
| bmSTART | bit 7 | Write: initiate START condition | | bmSTART | bit 7 | Write: initiate START condition |
| bmSTOP | bit 6 | Write: initiate STOP condition | | bmSTOP | bit 6 | Write: initiate STOP condition |
| bmLASTRD | bit 5 | Write: signal last read byte (NACK after next read) | | bmLASTRD | bit 5 | Write: signal last read byte (NACK after next read) |
| bmDONE | bit 2 | Read: byte transfer complete | | bmDONE | bit 2 | Read: byte transfer complete |
| bmACK | bit 1 | Read: ACK received from slave | | bmACK | bit 1 | Read: ACK received from slave |
| bmBERR | bit 0 | Read: bus error detected | | bmBERR | bit 0 | Read: bus error detected |
## Bus Speed ## Bus Speed
The I2C bus operates at 400 kHz. The speed is set through two mechanisms: The I2C bus operates at 400 kHz. The speed is set through two mechanisms:
1. **C2 EEPROM header** -- Config byte at offset 7 = 0x40, which the FX2 boot ROM uses to configure the I2C speed during initial EEPROM read. 1. **C2 EEPROM header** -- Config byte at offset 7 = 0x40, which the FX2 boot ROM uses to configure the I2C speed during initial EEPROM read.
2. **Firmware/software** -- I2CTL = `bm400KHZ` (written by the custom firmware and init table). 2. **Firmware/software** -- I2CTL = `bm400KHZ` (written by the custom firmware and init table).
## Known Bus Devices ## Known Bus Devices
| 7-bit Address | Wire Write | Wire Read | Identity | | 7-bit Address | Wire Write | Wire Read | Identity |
|---------------|-----------|----------|----------| |---------------|-----------|----------|----------|
| 0x08 | 0x10 | 0x11 | BCM4500 demodulator | | 0x08 | 0x10 | 0x11 | BCM4500 demodulator |
| 0x10 | 0x20 | 0x21 | Tuner or LNB controller | | 0x10 | 0x20 | 0x21 | Tuner or LNB controller |
| 0x51 | 0xA2 | 0xA3 | Configuration EEPROM (24Cxx-family) | | 0x51 | 0xA2 | 0xA3 | Configuration EEPROM (24Cxx-family) |
These addresses were confirmed via the I2C_BUS_SCAN command (0xB4) in custom firmware v3.01.0, which probes all 7-bit addresses from 0x01 to 0x77. These addresses were confirmed via the I2C_BUS_SCAN command (0xB4) in custom firmware v3.01.0, which probes all 7-bit addresses from 0x01 to 0x77.
### BCM4500 Demodulator (0x08) ### BCM4500 Demodulator (0x08)
The primary device for all demodulation operations. Register access uses the [indirect register protocol](/bcm4500/demodulator/) through registers 0xA6, 0xA7, and 0xA8. Direct registers 0xA2, 0xA4, and 0xF9 provide status information. The primary device for all demodulation operations. Register access uses the [indirect register protocol](/bcm4500/demodulator/) through registers 0xA6, 0xA7, and 0xA8. Direct registers 0xA2, 0xA4, and 0xF9 provide status information.
The v2.13 firmware also probes alternate addresses 0x7F and 0x3F at startup to detect which demodulator variant is present. The v2.13 firmware also probes alternate addresses 0x7F and 0x3F at startup to detect which demodulator variant is present.
### Tuner/LNB Controller (0x10) ### Tuner/LNB Controller (0x10)
Likely a tuner IC or LNB controller. In normal operation, the BCM4500 accesses this device internally for tuning. It is also directly addressable on the shared I2C bus. The kernel driver does not directly communicate with this device. Likely a tuner IC or LNB controller. In normal operation, the BCM4500 accesses this device internally for tuning. It is also directly addressable on the shared I2C bus. The kernel driver does not directly communicate with this device.
### Configuration EEPROM (0x51) ### Configuration EEPROM (0x51)
A 24Cxx-family serial EEPROM that stores: A 24Cxx-family serial EEPROM that stores:
- Device serial number (read by GET_SERIAL_NUMBER, 0x93) - Device serial number (read by GET_SERIAL_NUMBER, 0x93)
- Hardware platform ID (read by GET_FPGA_VERS, 0x95) - Hardware platform ID (read by GET_FPGA_VERS, 0x95)
- Calibration data - Calibration data
## Bus Topology ## Bus Topology
``` ```
FX2 I2C Master FX2 I2C Master
(I2CS/I2DAT/I2CTL) (I2CS/I2DAT/I2CTL)
| |
+----------+-----------+ +----------+-----------+
| | | | | |
BCM4500 Tuner/LNB EEPROM BCM4500 Tuner/LNB EEPROM
(0x08) (0x10) (0x51) (0x08) (0x10) (0x51)
``` ```
All three devices share the same SCL/SDA lines. The FX2's hardware I2C controller manages bus arbitration and clock stretching detection. All three devices share the same SCL/SDA lines. The FX2's hardware I2C controller manages bus arbitration and clock stretching detection.
## Combined Write-Read Protocol ## Combined Write-Read Protocol
All BCM4500 register reads use the I2C combined write-read protocol with a repeated START condition. This is required because the BCM4500 uses a register-addressed protocol where the register number must be sent in a write phase before the read phase. All BCM4500 register reads use the I2C combined write-read protocol with a repeated START condition. This is required because the BCM4500 uses a register-addressed protocol where the register number must be sent in a write phase before the read phase.
``` ```
Complete I2C transaction for reading register 0xA2 from device 0x08: Complete I2C transaction for reading register 0xA2 from device 0x08:
Phase 1 (Write): Phase 1 (Write):
[S] [0x10] [ACK] [0xA2] [ACK] [S] [0x10] [ACK] [0xA2] [ACK]
| | | | | | | | | |
| | | | +-- BCM4500 ACKs register address | | | | +-- BCM4500 ACKs register address
| | | +--------- Register address byte | | | +--------- Register address byte
| | +---------------- BCM4500 ACKs its device address | | +---------------- BCM4500 ACKs its device address
| +----------------------- Device address (0x08 << 1) = 0x10 (write) | +----------------------- Device address (0x08 << 1) = 0x10 (write)
+---------------------------- START condition +---------------------------- START condition
Phase 2 (Read with Repeated START): Phase 2 (Read with Repeated START):
[Sr] [0x11] [ACK] [DATA] [NACK] [P] [Sr] [0x11] [ACK] [DATA] [NACK] [P]
| | | | | | | | | | | |
| | | | | +-- STOP condition | | | | | +-- STOP condition
| | | | +--------- Master NACKs (last byte) | | | | +--------- Master NACKs (last byte)
| | | +---------------- Register data | | | +---------------- Register data
| | +----------------------- BCM4500 ACKs its device address | | +----------------------- BCM4500 ACKs its device address
| +------------------------------ Device address (0x08 << 1 | 1) = 0x11 (read) | +------------------------------ Device address (0x08 << 1 | 1) = 0x11 (read)
+------------------------------------ REPEATED START (no STOP between phases) +------------------------------------ REPEATED START (no STOP between phases)
``` ```
The repeated START (Sr) is essential. A STOP between phases would release the bus, and the BCM4500 would lose the register address context. The repeated START (Sr) is essential. A STOP between phases would release the bus, and the BCM4500 would lose the register address context.
### FX2 SFR Sequence for Combined Read ### FX2 SFR Sequence for Combined Read
```c title="Combined Write-Read Implementation" ```c title="Combined Write-Read Implementation"
// Phase 1: Write register address // Phase 1: Write register address
I2CS |= bmSTART; // Generate START I2CS |= bmSTART; // Generate START
I2DAT = 0x10; // Write: device addr + W I2DAT = 0x10; // Write: device addr + W
// wait bmDONE, check bmACK // wait bmDONE, check bmACK
I2DAT = 0xA2; // Write: register address I2DAT = 0xA2; // Write: register address
// wait bmDONE, check bmACK // wait bmDONE, check bmACK
// Phase 2: Read with repeated START // Phase 2: Read with repeated START
I2CS |= bmSTART; // Generate REPEATED START (no STOP first!) I2CS |= bmSTART; // Generate REPEATED START (no STOP first!)
I2DAT = 0x11; // Write: device addr + R I2DAT = 0x11; // Write: device addr + R
// wait bmDONE, check bmACK // wait bmDONE, check bmACK
I2CS |= bmLASTRD; // Signal this is the last read byte I2CS |= bmLASTRD; // Signal this is the last read byte
tmp = I2DAT; // Dummy read (triggers first clock burst) tmp = I2DAT; // Dummy read (triggers first clock burst)
// wait bmDONE // wait bmDONE
I2CS |= bmSTOP; // Generate STOP after reading I2CS |= bmSTOP; // Generate STOP after reading
data = I2DAT; // Read actual data byte data = I2DAT; // Read actual data byte
// wait bmSTOP to clear // wait bmSTOP to clear
``` ```
<Aside type="danger" title="STOP Condition Warning"> <Aside type="danger" title="STOP Condition Warning">
Do NOT issue `I2CS |= bmSTOP` when no I2C transaction is active. This corrupts the FX2 I2C controller state machine. See [I2C STOP Corruption Bug](/i2c/stop-corruption-bug/) for the full analysis. Do NOT issue `I2CS |= bmSTOP` when no I2C transaction is active. This corrupts the FX2 I2C controller state machine. See [I2C STOP Corruption Bug](/i2c/stop-corruption-bug/) for the full analysis.
</Aside> </Aside>
## Timeout Protection ## Timeout Protection
The fx2lib I2C functions poll `bmDONE` with no timeout: The fx2lib I2C functions poll `bmDONE` with no timeout:
```c title="fx2lib Original Code (Vulnerable)" ```c title="fx2lib Original Code (Vulnerable)"
while (!(I2CS & bmDONE) && !cancel_i2c_trans); while (!(I2CS & bmDONE) && !cancel_i2c_trans);
``` ```
Since `cancel_i2c_trans` is never set during normal operation, these loops are effectively infinite. If a slave holds SCL low or a bus error prevents bmDONE from asserting, the firmware hangs. Since `cancel_i2c_trans` is never set during normal operation, these loops are effectively infinite. If a slave holds SCL low or a bus error prevents bmDONE from asserting, the firmware hangs.
The custom firmware replaces all fx2lib I2C functions with timeout-protected wrappers: The custom firmware replaces all fx2lib I2C functions with timeout-protected wrappers:
```c title="Timeout-Protected I2C Wait" ```c title="Timeout-Protected I2C Wait"
#define I2C_TIMEOUT 6000 #define I2C_TIMEOUT 6000
static BOOL i2c_wait_done(void) { static BOOL i2c_wait_done(void) {
WORD timeout = I2C_TIMEOUT; WORD timeout = I2C_TIMEOUT;
while (!(I2CS & bmDONE)) { while (!(I2CS & bmDONE)) {
if (--timeout == 0) return FALSE; if (--timeout == 0) return FALSE;
} }
return TRUE; return TRUE;
} }
``` ```
A WORD counter of 6000 decremented in a tight SDCC-compiled loop at 48 MHz gives approximately 5--10 ms per wait. At 400 kHz I2C, a single byte transfer takes 22.5 us, so the timeout provides over 200x margin for normal operations while bounding the worst case. A WORD counter of 6000 decremented in a tight SDCC-compiled loop at 48 MHz gives approximately 5--10 ms per wait. At 400 kHz I2C, a single byte transfer takes 22.5 us, so the timeout provides over 200x margin for normal operations while bounding the worst case.

View File

@ -1,167 +1,167 @@
--- ---
title: I2C STOP Corruption Bug title: I2C STOP Corruption Bug
description: Root cause analysis of the spurious I2C STOP condition that corrupted the FX2 controller state during boot. description: Root cause analysis of the spurious I2C STOP condition that corrupted the FX2 controller state during boot.
--- ---
import { Steps, Aside, Badge } from '@astrojs/starlight/components'; import { Steps, Aside, Badge } from '@astrojs/starlight/components';
During development of the custom firmware v3.01.0, the BOOT_8PSK (0x89) command caused the FX2 to hang for over 10 seconds, making the USB device completely unresponsive. The root cause was traced to a single line of code: a spurious I2C STOP condition issued when no transaction was active. During development of the custom firmware v3.01.0, the BOOT_8PSK (0x89) command caused the FX2 to hang for over 10 seconds, making the USB device completely unresponsive. The root cause was traced to a single line of code: a spurious I2C STOP condition issued when no transaction was active.
<Aside type="danger" title="Critical Hardware Bug"> <Aside type="danger" title="Critical Hardware Bug">
Sending `I2CS |= bmSTOP` when no I2C transaction is active (no prior START, bus idle) corrupts the FX2 I2C controller's internal state machine. The bmSTOP bit may not self-clear, and subsequent START conditions fail to detect ACK from slaves. The Cypress TRM does not explicitly warn against this. Sending `I2CS |= bmSTOP` when no I2C transaction is active (no prior START, bus idle) corrupts the FX2 I2C controller's internal state machine. The bmSTOP bit may not self-clear, and subsequent START conditions fail to detect ACK from slaves. The Cypress TRM does not explicitly warn against this.
</Aside> </Aside>
## The Problem ## The Problem
The boot function originally included a "bus reset" step before any I2C communication: The boot function originally included a "bus reset" step before any I2C communication:
```c title="Broken Code" ```c title="Broken Code"
I2CS |= bmSTOP; I2CS |= bmSTOP;
i2c_wait_stop(); i2c_wait_stop();
``` ```
This pattern appears in various FX2 example code and seems reasonable -- send a STOP to ensure the I2C bus is in a known idle state before starting fresh. On the FX2's I2C controller hardware, this is incorrect. This pattern appears in various FX2 example code and seems reasonable -- send a STOP to ensure the I2C bus is in a known idle state before starting fresh. On the FX2's I2C controller hardware, this is incorrect.
## Root Cause Analysis ## Root Cause Analysis
The root cause was discovered through a series of incremental debug modes added to the BOOT_8PSK handler. Each mode executes a subset of the full boot sequence, isolating which step introduces the failure. The root cause was discovered through a series of incremental debug modes added to the BOOT_8PSK handler. Each mode executes a subset of the full boot sequence, isolating which step introduces the failure.
### Debug Mode Results ### Debug Mode Results
| wValue | Action | Result | Key Observation | | wValue | Action | Result | Key Observation |
|--------|--------|--------|-----------------| |--------|--------|--------|-----------------|
| 0x80 | No-op: return status only | <Badge text="Works" variant="success" /> | Baseline | | 0x80 | No-op: return status only | <Badge text="Works" variant="success" /> | Baseline |
| 0x81 | GPIO + power + delays (no I2C) | <Badge text="Works" variant="success" /> | Power sequencing is correct | | 0x81 | GPIO + power + delays (no I2C) | <Badge text="Works" variant="success" /> | Power sequencing is correct |
| 0x82 | GPIO + power + bmSTOP + I2C probe | <Badge text="Fails" variant="danger" /> | bmSTOP corrupts I2C | | 0x82 | GPIO + power + bmSTOP + I2C probe | <Badge text="Fails" variant="danger" /> | bmSTOP corrupts I2C |
| 0x83 | GPIO + power + bmSTOP + probe + init | <Badge text="Fails" variant="danger" /> | Same root cause | | 0x83 | GPIO + power + bmSTOP + probe + init | <Badge text="Fails" variant="danger" /> | Same root cause |
| 0x84 | I2C probe only (chip already powered) | <Badge text="Works" variant="success" /> | BCM4500 is alive | | 0x84 | I2C probe only (chip already powered) | <Badge text="Works" variant="success" /> | BCM4500 is alive |
| 0x85 | GPIO + power + probe (**no bmSTOP**) | <Badge text="Works" variant="success" /> | Confirms bmSTOP is the cause | | 0x85 | GPIO + power + probe (**no bmSTOP**) | <Badge text="Works" variant="success" /> | Confirms bmSTOP is the cause |
### Three Key Observations ### Three Key Observations
1. **Mode 0x82 fails but mode 0x85 succeeds.** These modes are identical except that 0x82 issues `I2CS |= bmSTOP` before the probe and 0x85 does not. The bmSTOP is the only difference. 1. **Mode 0x82 fails but mode 0x85 succeeds.** These modes are identical except that 0x82 issues `I2CS |= bmSTOP` before the probe and 0x85 does not. The bmSTOP is the only difference.
2. **Mode 0x84 succeeds immediately after 0x82 fails.** Mode 0x84 performs a plain I2C combined read with no GPIO manipulation or bus reset. If called after a failed 0x82, it succeeds. This proves the BCM4500 was alive and responding -- the FX2 I2C controller was in a bad state, not the bus or the slave. 2. **Mode 0x84 succeeds immediately after 0x82 fails.** Mode 0x84 performs a plain I2C combined read with no GPIO manipulation or bus reset. If called after a failed 0x82, it succeeds. This proves the BCM4500 was alive and responding -- the FX2 I2C controller was in a bad state, not the bus or the slave.
3. **Raw I2C reads via command 0xB5 succeed after 0x82 fails.** Command 0xB5 uses the same `i2c_combined_read` function. Running it from the host after a failed 0x82 returns valid data from the BCM4500. 3. **Raw I2C reads via command 0xB5 succeed after 0x82 fails.** Command 0xB5 uses the same `i2c_combined_read` function. Running it from the host after a failed 0x82 returns valid data from the BCM4500.
## What Happens Inside the FX2 ## What Happens Inside the FX2
The FX2's I2C master controller is a hardware peripheral accessed through the I2CS, I2DAT, and I2CTL SFRs. The controller implements an I2C state machine in silicon. Writing bmSTOP to I2CS instructs the hardware to generate a STOP condition (SDA rising while SCL is high). The FX2's I2C master controller is a hardware peripheral accessed through the I2CS, I2DAT, and I2CTL SFRs. The controller implements an I2C state machine in silicon. Writing bmSTOP to I2CS instructs the hardware to generate a STOP condition (SDA rising while SCL is high).
When no I2C transaction is active -- no prior START has been issued, and the bus is idle -- writing bmSTOP puts the controller into an inconsistent internal state: When no I2C transaction is active -- no prior START has been issued, and the bus is idle -- writing bmSTOP puts the controller into an inconsistent internal state:
- The bmSTOP bit may not clear properly (it is supposed to self-clear when the STOP condition completes) - The bmSTOP bit may not clear properly (it is supposed to self-clear when the STOP condition completes)
- Subsequent START conditions fail to generate proper clock sequences - Subsequent START conditions fail to generate proper clock sequences
- ACK detection from slaves becomes unreliable - ACK detection from slaves becomes unreliable
The Cypress TRM describes STOP as a step that follows a completed read or write transaction. It is not documented as a standalone bus-reset mechanism. The Cypress TRM describes STOP as a step that follows a completed read or write transaction. It is not documented as a standalone bus-reset mechanism.
## The Fix ## The Fix
The fix is a single deletion. Remove the spurious STOP from the boot sequence: The fix is a single deletion. Remove the spurious STOP from the boot sequence:
```c title="Before (Broken)" ```c title="Before (Broken)"
/* "Reset" I2C bus */ /* "Reset" I2C bus */
I2CS |= bmSTOP; I2CS |= bmSTOP;
i2c_wait_stop(); i2c_wait_stop();
``` ```
```c title="After (Correct)" ```c title="After (Correct)"
/* NOTE: Do NOT send I2CS bmSTOP here. Sending STOP when no /* NOTE: Do NOT send I2CS bmSTOP here. Sending STOP when no
* transaction is active corrupts the FX2 I2C controller state, * transaction is active corrupts the FX2 I2C controller state,
* causing subsequent START+ACK detection to fail. The I2C bus * causing subsequent START+ACK detection to fail. The I2C bus
* will be in a clean state when we reach the probe step -- * will be in a clean state when we reach the probe step --
* any prior transaction ended with STOP. */ * any prior transaction ended with STOP. */
``` ```
The correct approach is to simply proceed with a new START condition. If the bus is idle (after power-on or after the previous transaction completed normally), the START succeeds and the controller enters its normal operating state. The hardware handles bus arbitration automatically. The correct approach is to simply proceed with a new START condition. If the bus is idle (after power-on or after the previous transaction completed normally), the START succeeds and the controller enters its normal operating state. The hardware handles bus arbitration automatically.
## Corrected Boot Sequence ## Corrected Boot Sequence
```c title="bcm4500_boot() -- Corrected" ```c title="bcm4500_boot() -- Corrected"
static BOOL bcm4500_boot(void) { static BOOL bcm4500_boot(void) {
boot_stage = 1; boot_stage = 1;
cancel_i2c_trans = FALSE; cancel_i2c_trans = FALSE;
/* P3.7, P3.6, P3.5 HIGH (idle state for control lines) */ /* P3.7, P3.6, P3.5 HIGH (idle state for control lines) */
IOD |= 0xE0; IOD |= 0xE0;
/* Assert BCM4500 hardware RESET (P0.5 LOW) */ /* Assert BCM4500 hardware RESET (P0.5 LOW) */
OEA |= PIN_BCM_RESET; OEA |= PIN_BCM_RESET;
IOA &= ~PIN_BCM_RESET; IOA &= ~PIN_BCM_RESET;
/* No I2CS bmSTOP here -- see note above */ /* No I2CS bmSTOP here -- see note above */
/* Power on: P0.1 HIGH (enable), P0.2 LOW (disable off) */ /* Power on: P0.1 HIGH (enable), P0.2 LOW (disable off) */
OEA |= (PIN_PWR_EN | PIN_PWR_DIS); OEA |= (PIN_PWR_EN | PIN_PWR_DIS);
IOA = (IOA & ~PIN_PWR_DIS) | PIN_PWR_EN; IOA = (IOA & ~PIN_PWR_DIS) | PIN_PWR_EN;
boot_stage = 2; boot_stage = 2;
delay(30); /* power settle */ delay(30); /* power settle */
IOA |= PIN_BCM_RESET; /* release reset */ IOA |= PIN_BCM_RESET; /* release reset */
delay(50); /* BCM4500 POR + mask ROM boot */ delay(50); /* BCM4500 POR + mask ROM boot */
boot_stage = 3; boot_stage = 3;
/* I2C probe -- if this fails, the chip didn't respond */ /* I2C probe -- if this fails, the chip didn't respond */
if (!bcm_direct_read(BCM_REG_STATUS, &i2c_rd[0])) if (!bcm_direct_read(BCM_REG_STATUS, &i2c_rd[0]))
return FALSE; return FALSE;
/* ... register init blocks follow ... */ /* ... register init blocks follow ... */
} }
``` ```
## Boot Results After Fix ## Boot Results After Fix
| Metric | Value | | Metric | Value |
|--------|-------| |--------|-------|
| Boot time | ~90 ms total | | Boot time | ~90 ms total |
| config_status | 0x03 (STARTED + FW_LOADED) | | config_status | 0x03 (STARTED + FW_LOADED) |
| boot_stage | 0xFF (COMPLETE) | | boot_stage | 0xFF (COMPLETE) |
| Direct registers 0xA2-0xA8 | All return 0x02 (powered, not locked) | | Direct registers 0xA2-0xA8 | All return 0x02 (powered, not locked) |
| Signal lock | 0x00 (no lock -- dish not aimed) | | Signal lock | 0x00 (no lock -- dish not aimed) |
| USB responsiveness | No hang; fully responsive throughout | | USB responsiveness | No hang; fully responsive throughout |
## Test Scripts ## Test Scripts
The investigation was driven by a series of test scripts in the `tools/` directory: The investigation was driven by a series of test scripts in the `tools/` directory:
| Script | Purpose | | Script | Purpose |
|--------|---------| |--------|---------|
| `test_boot_debug.py` | Sends debug modes 0x80--0x83 sequentially | | `test_boot_debug.py` | Sends debug modes 0x80--0x83 sequentially |
| `test_i2c_debug.py` | Powers on via 0x81, runs bus scans, tests probe timing | | `test_i2c_debug.py` | Powers on via 0x81, runs bus scans, tests probe timing |
| `test_i2c_isolate.py` | Tests whether re-reset or insufficient delay causes failure | | `test_i2c_isolate.py` | Tests whether re-reset or insufficient delay causes failure |
| `test_i2c_pinpoint.py` | The definitive test: compares modes 0x84, 0x85, and 0x82 | | `test_i2c_pinpoint.py` | The definitive test: compares modes 0x84, 0x85, and 0x82 |
## Timeout Protection ## Timeout Protection
Even with the bmSTOP fix, timeout protection on all I2C operations is essential. The FX2's I2C controller has no hardware timeout -- if a slave holds SCL low (clock stretching) or a fault prevents bmDONE from asserting, the firmware spins forever. Even with the bmSTOP fix, timeout protection on all I2C operations is essential. The FX2's I2C controller has no hardware timeout -- if a slave holds SCL low (clock stretching) or a fault prevents bmDONE from asserting, the firmware spins forever.
The custom firmware replaces all fx2lib I2C functions with timeout-protected wrappers: The custom firmware replaces all fx2lib I2C functions with timeout-protected wrappers:
```c title="Timeout-Protected I2C Waits" ```c title="Timeout-Protected I2C Waits"
#define I2C_TIMEOUT 6000 #define I2C_TIMEOUT 6000
static BOOL i2c_wait_done(void) { static BOOL i2c_wait_done(void) {
WORD timeout = I2C_TIMEOUT; WORD timeout = I2C_TIMEOUT;
while (!(I2CS & bmDONE)) { while (!(I2CS & bmDONE)) {
if (--timeout == 0) return FALSE; if (--timeout == 0) return FALSE;
} }
return TRUE; return TRUE;
} }
static BOOL i2c_wait_stop(void) { static BOOL i2c_wait_stop(void) {
WORD timeout = I2C_TIMEOUT; WORD timeout = I2C_TIMEOUT;
while (I2CS & bmSTOP) { while (I2CS & bmSTOP) {
if (--timeout == 0) return FALSE; if (--timeout == 0) return FALSE;
} }
return TRUE; return TRUE;
} }
``` ```
A WORD counter of 6000 at 48 MHz gives approximately 5--10 ms per wait, providing over 200x margin above the 22.5 us required for a single byte transfer at 400 kHz. A WORD counter of 6000 at 48 MHz gives approximately 5--10 ms per wait, providing over 200x margin above the 22.5 us required for a single byte transfer at 400 kHz.
<Aside type="tip" title="FX2 Recovery"> <Aside type="tip" title="FX2 Recovery">
If the firmware hangs due to I2C issues, the device can be recovered without a physical unplug. The FX2's CPUCS register (0xE600) is accessible via the boot ROM's `bRequest=0xA0` handler, which runs at hardware priority. See [Boot Sequence](/usb/boot-sequence/) for the recovery procedure. If the firmware hangs due to I2C issues, the device can be recovered without a physical unplug. The FX2's CPUCS register (0xE600) is accessible via the boot ROM's `bRequest=0xA0` handler, which runs at hardware priority. See [Boot Sequence](/usb/boot-sequence/) for the recovery procedure.
</Aside> </Aside>

View File

@ -1,83 +1,83 @@
--- ---
title: SkyWalker-1 Documentation title: SkyWalker-1 Documentation
description: Reverse-engineered technical documentation for the Genpix SkyWalker-1 DVB-S USB 2.0 satellite receiver. description: Reverse-engineered technical documentation for the Genpix SkyWalker-1 DVB-S USB 2.0 satellite receiver.
template: splash template: splash
hero: hero:
title: SkyWalker-1 title: SkyWalker-1
tagline: Open-source reverse-engineered documentation for the Genpix SkyWalker-1 DVB-S USB 2.0 satellite receiver tagline: Open-source reverse-engineered documentation for the Genpix SkyWalker-1 DVB-S USB 2.0 satellite receiver
image: image:
file: ../../assets/skywalker-1-hero.jpg file: ../../assets/skywalker-1-hero.jpg
alt: Genpix Electronics SkyWalker-1 DVB-S USB satellite receiver alt: Genpix Electronics SkyWalker-1 DVB-S USB satellite receiver
actions: actions:
- text: Get Started - text: Get Started
link: /hardware/overview/ link: /hardware/overview/
icon: right-arrow icon: right-arrow
- text: Master Reference - text: Master Reference
link: /reference/master-reference/ link: /reference/master-reference/
variant: minimal variant: minimal
--- ---
import { CardGrid, Card, Aside } from '@astrojs/starlight/components'; import { CardGrid, Card, Aside } from '@astrojs/starlight/components';
The Genpix SkyWalker-1 is a standalone USB 2.0 DVB-S satellite receiver built around a Cypress FX2LP microcontroller and Broadcom BCM4500 demodulator. This project documents its complete internal architecture through Linux kernel driver analysis, Ghidra firmware reverse engineering across five firmware images, Windows BDA driver source review, and custom firmware development. The Genpix SkyWalker-1 is a standalone USB 2.0 DVB-S satellite receiver built around a Cypress FX2LP microcontroller and Broadcom BCM4500 demodulator. This project documents its complete internal architecture through Linux kernel driver analysis, Ghidra firmware reverse engineering across five firmware images, Windows BDA driver source review, and custom firmware development.
The result is a fully open-source technical reference covering every vendor command, register, GPIO pin, and data path -- from the USB control transfers down to the I2C bit timing on the BCM4500's indirect register protocol. The result is a fully open-source technical reference covering every vendor command, register, GPIO pin, and data path -- from the USB control transfers down to the I2C bit timing on the BCM4500's indirect register protocol.
**Supported modulations:** DVB-S (QPSK), Turbo QPSK, Turbo 8PSK, Turbo 16QAM, Digicipher II (Combo, Split I/Q, Offset QPSK), DSS (QPSK), and DVB-S BPSK. Symbol rates from 256 Ksps to 30 Msps across a 950--2150 MHz IF range. **Supported modulations:** DVB-S (QPSK), Turbo QPSK, Turbo 8PSK, Turbo 16QAM, Digicipher II (Combo, Split I/Q, Offset QPSK), DSS (QPSK), and DVB-S BPSK. Symbol rates from 256 Ksps to 30 Msps across a 950--2150 MHz IF range.
<Aside type="note"> <Aside type="note">
DVB-S2 is **not supported**. The BCM4500 predates the DVB-S2 standard and contains no LDPC or BCH decoder hardware. This is a silicon limitation -- no firmware update can change it. See the [DVB-S2 Incompatibility](/driver/dvb-s2/) section for the full investigation. DVB-S2 is **not supported**. The BCM4500 predates the DVB-S2 standard and contains no LDPC or BCH decoder hardware. This is a silicon limitation -- no firmware update can change it. See the [DVB-S2 Incompatibility](/driver/dvb-s2/) section for the full investigation.
</Aside> </Aside>
## Explore the Documentation ## Explore the Documentation
<CardGrid> <CardGrid>
<Card title="Hardware" icon="laptop"> <Card title="Hardware" icon="laptop">
FX2LP + BCM4500 architecture, GPIO pin maps, RF specifications, and board block diagram. FX2LP + BCM4500 architecture, GPIO pin maps, RF specifications, and board block diagram.
[Hardware Overview](/hardware/overview/) [Hardware Overview](/hardware/overview/)
</Card> </Card>
<Card title="USB Interface" icon="puzzle"> <Card title="USB Interface" icon="puzzle">
Vendor command reference, boot sequence, configuration status byte, and endpoint layout. Vendor command reference, boot sequence, configuration status byte, and endpoint layout.
[USB Interface](/usb/interface/) [USB Interface](/usb/interface/)
</Card> </Card>
<Card title="BCM4500" icon="setting"> <Card title="BCM4500" icon="setting">
Demodulator I2C protocol, indirect register access, tuning sequence, and GPIF streaming path. Demodulator I2C protocol, indirect register access, tuning sequence, and GPIF streaming path.
[Demodulator](/bcm4500/demodulator/) [Demodulator](/bcm4500/demodulator/)
</Card> </Card>
<Card title="LNB and DiSEqC" icon="rocket"> <Card title="LNB and DiSEqC" icon="rocket">
LNB voltage and tone control, DiSEqC 1.0/1.2 protocol, legacy Dish Network switches. LNB voltage and tone control, DiSEqC 1.0/1.2 protocol, legacy Dish Network switches.
[LNB Control](/lnb-diseqc/lnb-control/) [LNB Control](/lnb-diseqc/lnb-control/)
</Card> </Card>
<Card title="Firmware" icon="document"> <Card title="Firmware" icon="document">
Version comparison across five firmware images, custom v3.01.0 development, and storage formats. Version comparison across five firmware images, custom v3.01.0 development, and storage formats.
[Firmware Versions](/firmware/version-comparison/) [Firmware Versions](/firmware/version-comparison/)
</Card> </Card>
<Card title="Tools" icon="seti"> <Card title="Tools" icon="seti">
Python utilities for RAM loading, EEPROM flashing, transponder tuning, transport stream analysis, and hardware debugging. Python utilities for RAM loading, EEPROM flashing, transponder tuning, transport stream analysis, and hardware debugging.
[Firmware Loader](/tools/firmware-loader/) [Firmware Loader](/tools/firmware-loader/)
</Card> </Card>
</CardGrid> </CardGrid>
## Project Scope ## Project Scope
This documentation covers the complete reverse engineering of the SkyWalker-1 hardware and firmware: This documentation covers the complete reverse engineering of the SkyWalker-1 hardware and firmware:
- **5 firmware images** decompiled in Ghidra: v2.06.04, Rev.2 v2.10.04, and three v2.13 sub-variants - **5 firmware images** decompiled in Ghidra: v2.06.04, Rev.2 v2.10.04, and three v2.13 sub-variants
- **30 vendor USB commands** fully decoded with parameter formats and version-specific behavior - **30 vendor USB commands** fully decoded with parameter formats and version-specific behavior
- **Custom firmware** (v3.01.0) built from scratch with SDCC + fx2lib, including 7 new diagnostic commands - **Custom firmware** (v3.01.0) built from scratch with SDCC + fx2lib, including 7 new diagnostic commands
- **13 Python tools** for firmware management, satellite tuning, transport stream analysis, and hardware debugging - **13 Python tools** for firmware management, satellite tuning, transport stream analysis, and hardware debugging
- **I2C STOP corruption bug** discovered and fixed through incremental debug modes on the FX2 controller - **I2C STOP corruption bug** discovered and fixed through incremental debug modes on the FX2 controller
All source code, firmware binaries, analysis reports, and this documentation are available in the project repository. All source code, firmware binaries, analysis reports, and this documentation are available in the project repository.
## Support Genpix and the Leleka Foundation ## Support Genpix and the Leleka Foundation
Genpix Electronics is selling their remaining SkyWalker-1 inventory on eBay, with all net proceeds going to the [Leleka Foundation](https://www.leleka.org/) -- a US-based charitable organization providing medical and social support to individuals wounded and displaced by the conflict in Ukraine. Genpix Electronics is selling their remaining SkyWalker-1 inventory on eBay, with all net proceeds going to the [Leleka Foundation](https://www.leleka.org/) -- a US-based charitable organization providing medical and social support to individuals wounded and displaced by the conflict in Ukraine.
If you'd like to own one of these capable little receivers and support a good cause at the same time, check the [eBay listing from the official Genpix seller](https://www.ebay.com/itm/196142001978). New-in-box units ship via USPS Priority Mail. Thank you to Genpix for building the SkyWalker-1 and for directing their remaining stock toward something meaningful. If you'd like to own one of these capable little receivers and support a good cause at the same time, check the [eBay listing from the official Genpix seller](https://www.ebay.com/itm/196142001978). New-in-box units ship via USPS Priority Mail. Thank you to Genpix for building the SkyWalker-1 and for directing their remaining stock toward something meaningful.

View File

@ -1,273 +1,273 @@
--- ---
title: DiSEqC Protocol title: DiSEqC Protocol
description: DiSEqC 1.0/1.2 implementation with Manchester-encoded GPIO bit-bang, timing analysis, and command framing. description: DiSEqC 1.0/1.2 implementation with Manchester-encoded GPIO bit-bang, timing analysis, and command framing.
--- ---
import { Steps, Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components'; import { Steps, Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components';
The SkyWalker-1 implements DiSEqC (Digital Satellite Equipment Control) via Timer2-based GPIO bit-bang on the FX2 microcontroller. The algorithm is identical across all firmware versions -- only the data pin assignment changes per PCB revision. The SkyWalker-1 implements DiSEqC (Digital Satellite Equipment Control) via Timer2-based GPIO bit-bang on the FX2 microcontroller. The algorithm is identical across all firmware versions -- only the data pin assignment changes per PCB revision.
[Download DiSEqC PDF](/downloads/DiSEqC%20for%20the%20Skywalker-1.pdf) [Download DiSEqC PDF](/downloads/DiSEqC%20for%20the%20Skywalker-1.pdf)
## Protocol Diagrams ## Protocol Diagrams
The following diagrams document the Genpix BDA driver's DiSEqC extended property interface: The following diagrams document the Genpix BDA driver's DiSEqC extended property interface:
![DiSEqC Protocol Diagram Page 1](../../../assets/diagrams/DiSEqC%20for%20the%20Skywalker-1_page_1.svg) ![DiSEqC Protocol Diagram Page 1](../../../assets/diagrams/DiSEqC%20for%20the%20Skywalker-1_page_1.svg)
![DiSEqC Protocol Diagram Page 2](../../../assets/diagrams/DiSEqC%20for%20the%20Skywalker-1_page_2.svg) ![DiSEqC Protocol Diagram Page 2](../../../assets/diagrams/DiSEqC%20for%20the%20Skywalker-1_page_2.svg)
## Signal Architecture ## Signal Architecture
The firmware does **not** generate the 22 kHz carrier directly. GPIO P0.3 gates an external 22 kHz oscillator circuit on the PCB: The firmware does **not** generate the 22 kHz carrier directly. GPIO P0.3 gates an external 22 kHz oscillator circuit on the PCB:
``` ```
FX2 Firmware External Hardware Coax Cable FX2 Firmware External Hardware Coax Cable
+------------------+ +--------------------+ +------------------+ +------------------+ +--------------------+ +------------------+
| P0.3 (carrier) |---->| 22 kHz oscillator |---->| LNB power line | | P0.3 (carrier) |---->| 22 kHz oscillator |---->| LNB power line |
| (enable/disable) | | (gated by P0.3) | | (13V/18V + tone) | | (enable/disable) | | (gated by P0.3) | | (13V/18V + tone) |
| | | | | | | | | | | |
| P0.x (data bit) | | (internal firmware | | | | P0.x (data bit) | | (internal firmware | | |
| (firmware only) | | logic only) | | | | (firmware only) | | logic only) | | |
+------------------+ +--------------------+ +------------------+ +------------------+ +--------------------+ +------------------+
``` ```
The data pin (P0.7 / P0.4 / P0.0 depending on version) is used only internally by the firmware's Manchester encoding logic. It controls whether the carrier gate signal is cut short or held for the full bit period. The data pin (P0.7 / P0.4 / P0.0 depending on version) is used only internally by the firmware's Manchester encoding logic. It controls whether the carrier gate signal is cut short or held for the full bit period.
## Timer2 Configuration ## Timer2 Configuration
All firmware versions configure Timer2 identically during USB descriptor setup: All firmware versions configure Timer2 identically during USB descriptor setup:
| Parameter | Value | Notes | | Parameter | Value | Notes |
|-----------|-------|-------| |-----------|-------|-------|
| T2CON | `0x04` | Auto-reload mode, timer running | | T2CON | `0x04` | Auto-reload mode, timer running |
| RCAP2H | `0xF8` | Reload high byte | | RCAP2H | `0xF8` | Reload high byte |
| RCAP2L | `0x2F` | Reload low byte (reload = 63535) | | RCAP2L | `0x2F` | Reload low byte (reload = 63535) |
| CKCON.T2M | `0` | Timer2 clock = 48 MHz / 12 = 4 MHz | | CKCON.T2M | `0` | Timer2 clock = 48 MHz / 12 = 4 MHz |
**Tick period calculation:** **Tick period calculation:**
``` ```
FX2 master clock = 48 MHz FX2 master clock = 48 MHz
CKCON.T2M = 0 -> Timer2 clock = 48 MHz / 12 = 4 MHz CKCON.T2M = 0 -> Timer2 clock = 48 MHz / 12 = 4 MHz
Count per overflow = 65536 - 63535 = 2001 Count per overflow = 65536 - 63535 = 2001
Tick period = 2001 / 4,000,000 = 500.25 us ~ 500 us Tick period = 2001 / 4,000,000 = 500.25 us ~ 500 us
Tick frequency ~ 2.0 kHz Tick frequency ~ 2.0 kHz
``` ```
Timer2 runs continuously from power-on and is never stopped or reconfigured. It serves as a stable 500 us timebase for all DiSEqC operations. Timer2 runs continuously from power-on and is never stopped or reconfigured. It serves as a stable 500 us timebase for all DiSEqC operations.
## Manchester Encoding ## Manchester Encoding
Each DiSEqC bit consists of 3 Timer2 ticks (3 x 500 us = 1.5 ms): Each DiSEqC bit consists of 3 Timer2 ticks (3 x 500 us = 1.5 ms):
<Tabs> <Tabs>
<TabItem label="Data '0'"> <TabItem label="Data '0'">
**Data '0'** -- 2/3 tone, 1/3 silence (1.0 ms carrier + 0.5 ms silence): **Data '0'** -- 2/3 tone, 1/3 silence (1.0 ms carrier + 0.5 ms silence):
``` ```
Tick 1 Tick 2 Tick 3 Tick 1 Tick 2 Tick 3
(500 us) (500 us) (500 us) (500 us) (500 us) (500 us)
P0.3: _____|========|========|________| P0.3: _____|========|========|________|
^tone ON ^tone OFF ^tone ON ^tone OFF
(setup gap) (1.0 ms carrier) (0.5 ms silence) (setup gap) (1.0 ms carrier) (0.5 ms silence)
``` ```
</TabItem> </TabItem>
<TabItem label="Data '1'"> <TabItem label="Data '1'">
**Data '1'** -- 1/3 tone, 2/3 silence (0.5 ms carrier + 1.0 ms silence): **Data '1'** -- 1/3 tone, 2/3 silence (0.5 ms carrier + 1.0 ms silence):
``` ```
Tick 1 Tick 2 Tick 3 Tick 1 Tick 2 Tick 3
(500 us) (500 us) (500 us) (500 us) (500 us) (500 us)
P0.3: _____|========|________|________| P0.3: _____|========|________|________|
^tone ON ^tone OFF early ^tone ON ^tone OFF early
(setup gap) (0.5 ms carrier) (1.0 ms silence) (setup gap) (0.5 ms carrier) (1.0 ms silence)
``` ```
</TabItem> </TabItem>
</Tabs> </Tabs>
### Bit Symbol Implementation ### Bit Symbol Implementation
Decompiled from Rev.2 `FUN_CODE_213c`: Decompiled from Rev.2 `FUN_CODE_213c`:
```c title="DiSEqC bit symbol function" ```c title="DiSEqC bit symbol function"
void diseqc_bit_symbol(void) { void diseqc_bit_symbol(void) {
wait_TF2(); // Tick 1: inter-bit gap (500 us) wait_TF2(); // Tick 1: inter-bit gap (500 us)
P0 |= 0x08; // P0.3 = 1 -> 22 kHz carrier ON P0 |= 0x08; // P0.3 = 1 -> 22 kHz carrier ON
wait_TF2(); // Tick 2: carrier period (500 us) wait_TF2(); // Tick 2: carrier period (500 us)
if (data_pin != 0) { // If data = '1': if (data_pin != 0) { // If data = '1':
P0 &= 0xF7; // P0.3 = 0 -> carrier OFF (short pulse) P0 &= 0xF7; // P0.3 = 0 -> carrier OFF (short pulse)
} }
wait_TF2(); // Tick 3: final period (500 us) wait_TF2(); // Tick 3: final period (500 us)
P0 &= 0xF7; // P0.3 = 0 -> carrier always OFF at end P0 &= 0xF7; // P0.3 = 0 -> carrier always OFF at end
} }
``` ```
The `wait_TF2()` function is the lowest-level timing primitive -- a busy-wait on the Timer2 overflow flag: The `wait_TF2()` function is the lowest-level timing primitive -- a busy-wait on the Timer2 overflow flag:
```c title="Timer2 tick wait (identical across all versions)" ```c title="Timer2 tick wait (identical across all versions)"
void wait_TF2(void) { void wait_TF2(void) {
while (TF2 == 0) {} // Poll Timer2 overflow flag while (TF2 == 0) {} // Poll Timer2 overflow flag
TF2 = 0; // Clear flag for next tick TF2 = 0; // Clear flag for next tick
} }
``` ```
## Byte Transmission ## Byte Transmission
Each DiSEqC byte is 9 bits: 8 data bits (MSB first) + 1 odd parity bit. Each DiSEqC byte is 9 bits: 8 data bits (MSB first) + 1 odd parity bit.
```c title="DiSEqC byte transmit (from Rev.2 FUN_CODE_07d1)" ```c title="DiSEqC byte transmit (from Rev.2 FUN_CODE_07d1)"
void diseqc_send_byte(char first_byte, byte data) { void diseqc_send_byte(char first_byte, byte data) {
byte ones_count = 0; byte ones_count = 0;
if (first_byte == 0) TF2 = 0; // Sync timer on first byte if (first_byte == 0) TF2 = 0; // Sync timer on first byte
for (char i = 8; i > 0; i--) { // 8 bits, MSB first for (char i = 8; i > 0; i--) { // 8 bits, MSB first
if (data & 0x80) { if (data & 0x80) {
data_pin = 1; // Set data = '1' data_pin = 1; // Set data = '1'
diseqc_bit_symbol(); diseqc_bit_symbol();
ones_count++; ones_count++;
} else { } else {
data_pin = 0; // Set data = '0' data_pin = 0; // Set data = '0'
diseqc_bit_symbol(); diseqc_bit_symbol();
} }
data <<= 1; // Next bit data <<= 1; // Next bit
} }
data_pin = ~ones_count & 1; // Odd parity: '1' if even count data_pin = ~ones_count & 1; // Odd parity: '1' if even count
diseqc_bit_symbol(); // Transmit parity bit diseqc_bit_symbol(); // Transmit parity bit
} }
``` ```
**Timing per byte:** 9 bits x 1.5 ms = 13.5 ms **Timing per byte:** 9 bits x 1.5 ms = 13.5 ms
## DiSEqC Command Sequence ## DiSEqC Command Sequence
The full command flow for sending a DiSEqC message via vendor command `0x8D` (`SEND_DISEQC_COMMAND`): The full command flow for sending a DiSEqC message via vendor command `0x8D` (`SEND_DISEQC_COMMAND`):
<Steps> <Steps>
1. **Read wLength** from USB SETUP packet (`0xE6BE`) to determine message byte count 1. **Read wLength** from USB SETUP packet (`0xE6BE`) to determine message byte count
2. **Disable 22 kHz carrier** by clearing P0.3 (ensuring a clean start state) 2. **Disable 22 kHz carrier** by clearing P0.3 (ensuring a clean start state)
3. **Pre-transmission delay** of 15 Timer2 ticks (7.5 ms) for LNB voltage settling 3. **Pre-transmission delay** of 15 Timer2 ticks (7.5 ms) for LNB voltage settling
4. **Transmit message bytes** if wLength > 0: iterate through EP0BUF, sending each byte via Manchester-encoded bit-bang (8 data bits + odd parity, 3 Timer2 ticks per bit) 4. **Transmit message bytes** if wLength > 0: iterate through EP0BUF, sending each byte via Manchester-encoded bit-bang (8 data bits + odd parity, 3 Timer2 ticks per bit)
5. **Or send tone burst** if wLength == 0: 5. **Or send tone burst** if wLength == 0:
- `wValue == 0`: Tone Burst A (25 Timer2 ticks = 12.5 ms of unmodulated carrier) - `wValue == 0`: Tone Burst A (25 Timer2 ticks = 12.5 ms of unmodulated carrier)
- `wValue != 0`: Tone Burst B (transmitted as `0xFF` byte pattern through the bit-bang function) - `wValue != 0`: Tone Burst B (transmitted as `0xFF` byte pattern through the bit-bang function)
</Steps> </Steps>
## USB Command Format ## USB Command Format
### Full DiSEqC Message (3-6 bytes) ### Full DiSEqC Message (3-6 bytes)
``` ```
USB SETUP: USB SETUP:
bmRequestType = 0x40 (vendor, host-to-device) bmRequestType = 0x40 (vendor, host-to-device)
bRequest = 0x8D (SEND_DISEQC_COMMAND) bRequest = 0x8D (SEND_DISEQC_COMMAND)
wValue = msg[0] (framing byte, typically 0xE0 or 0xE1) wValue = msg[0] (framing byte, typically 0xE0 or 0xE1)
wIndex = 0x0000 wIndex = 0x0000
wLength = message length (3-6) wLength = message length (3-6)
EP0 Data: EP0 Data:
Byte 0: Framing byte (e.g., 0xE0 = command from master, no reply expected) Byte 0: Framing byte (e.g., 0xE0 = command from master, no reply expected)
Byte 1: Address byte (e.g., 0x10 = any LNB, 0x11 = LNB 1) Byte 1: Address byte (e.g., 0x10 = any LNB, 0x11 = LNB 1)
Byte 2: Command byte (e.g., 0x38 = Write N0, committed switch port) Byte 2: Command byte (e.g., 0x38 = Write N0, committed switch port)
Byte 3: Data byte 0 (optional, port selection bits) Byte 3: Data byte 0 (optional, port selection bits)
Byte 4: Data byte 1 (optional) Byte 4: Data byte 1 (optional)
Byte 5: Data byte 2 (optional) Byte 5: Data byte 2 (optional)
``` ```
### Tone Burst (Mini DiSEqC) ### Tone Burst (Mini DiSEqC)
``` ```
USB SETUP: USB SETUP:
bmRequestType = 0x40 bmRequestType = 0x40
bRequest = 0x8D bRequest = 0x8D
wValue = 0x00 (Burst A) or 0x01 (Burst B) wValue = 0x00 (Burst A) or 0x01 (Burst B)
wIndex = 0x0000 wIndex = 0x0000
wLength = 0 (zero length signals tone burst mode) wLength = 0 (zero length signals tone burst mode)
``` ```
## Windows BDA Driver Interface ## Windows BDA Driver Interface
The Windows driver exposes DiSEqC through a BDA extended property GUID: The Windows driver exposes DiSEqC through a BDA extended property GUID:
```c title="BDA Extended Property GUID" ```c title="BDA Extended Property GUID"
// {0B5221EB-F4C4-4976-B959-EF74427464D9} // {0B5221EB-F4C4-4976-B959-EF74427464D9}
#define STATIC_KSPROPSETID_BdaExtendedProperty \ #define STATIC_KSPROPSETID_BdaExtendedProperty \
0x0B5221EB, 0xF4C4, 0x4976, 0xB9, 0x59, 0xEF, 0x74, 0x42, 0x74, 0x64, 0xD9 0x0B5221EB, 0xF4C4, 0x4976, 0xB9, 0x59, 0xEF, 0x74, 0x42, 0x74, 0x64, 0xD9
``` ```
The DiSEqC command structure: The DiSEqC command structure:
```c title="DISEQC_COMMAND structure" ```c title="DISEQC_COMMAND structure"
typedef enum enSimpleToneBurst { typedef enum enSimpleToneBurst {
SEC_MINI_A, SEC_MINI_A,
SEC_MINI_B SEC_MINI_B
} SIMPLE_TONE_BURST; } SIMPLE_TONE_BURST;
typedef struct __DISEQC_COMMAND { typedef struct __DISEQC_COMMAND {
UCHAR ucMessage[6]; // Framing, Address, Command, Data[0..2] UCHAR ucMessage[6]; // Framing, Address, Command, Data[0..2]
UCHAR ucMessageLength; // 3-6 for DiSEqC; 1 for tone burst UCHAR ucMessageLength; // 3-6 for DiSEqC; 1 for tone burst
} DISEQC_COMMAND; } DISEQC_COMMAND;
``` ```
For tone burst commands, set `ucMessageLength = 1` and `ucMessage[0]` to either `SEC_MINI_A` (0x00) or `SEC_MINI_B` (0x01). For tone burst commands, set `ucMessageLength = 1` and `ucMessage[0]` to either `SEC_MINI_A` (0x00) or `SEC_MINI_B` (0x01).
## Data Pin Assignment Per Version ## Data Pin Assignment Per Version
The DiSEqC algorithm is identical across all firmware versions. Only the data pin changes per PCB revision: The DiSEqC algorithm is identical across all firmware versions. Only the data pin changes per PCB revision:
| Firmware Version | Data Pin | Carrier Pin | Byte Transmit Function | Bit Symbol Function | Timer Wait | | Firmware Version | Data Pin | Carrier Pin | Byte Transmit Function | Bit Symbol Function | Timer Wait |
|------------------|----------|-------------|----------------------|--------------------|-----------:| |------------------|----------|-------------|----------------------|--------------------|-----------:|
| v2.06 | **P0.7** | P0.3 | `0x2098` | `0x23B5` | `0x24C6` | | v2.06 | **P0.7** | P0.3 | `0x2098` | `0x23B5` | `0x24C6` |
| Rev.2 v2.10 | **P0.4** | P0.3 | `FUN_CODE_07d1` | `FUN_CODE_213c` | `FUN_CODE_225f` | | Rev.2 v2.10 | **P0.4** | P0.3 | `FUN_CODE_07d1` | `FUN_CODE_213c` | `FUN_CODE_225f` |
| v2.13 FW1 | **P0.0** | P0.3 | `FUN_CODE_2060` | `FUN_CODE_22f3` | `func_0x2431` | | v2.13 FW1 | **P0.0** | P0.3 | `FUN_CODE_2060` | `FUN_CODE_22f3` | `func_0x2431` |
| Custom v3.01.0 | **P0.7** | P0.3 | `diseqc_tone_burst()` | (inline) | (inline) | | Custom v3.01.0 | **P0.7** | P0.3 | `diseqc_tone_burst()` | (inline) | (inline) |
<Aside type="note"> <Aside type="note">
The custom v3.01.0 firmware uses the v2.06 pin assignment (P0.7 for data) since it targets the same original PCB revision. If flashing custom firmware to a Rev.2 board, the DiSEqC data pin would need to be changed to P0.4. The custom v3.01.0 firmware uses the v2.06 pin assignment (P0.7 for data) since it targets the same original PCB revision. If flashing custom firmware to a Rev.2 board, the DiSEqC data pin would need to be changed to P0.4.
</Aside> </Aside>
## CPU Clock Compensation ## CPU Clock Compensation
The delay function used before DiSEqC transmission adjusts its loop count based on the FX2 CPU clock speed: The delay function used before DiSEqC transmission adjusts its loop count based on the FX2 CPU clock speed:
```c title="Clock-aware delay function" ```c title="Clock-aware delay function"
void delay(byte high, byte low) { void delay(byte high, byte low) {
byte clkspd = CPUCS & 0x18; // CPUCS[4:3] = clock speed bits byte clkspd = CPUCS & 0x18; // CPUCS[4:3] = clock speed bits
if (clkspd == 0x00) { // 12 MHz: halve the count if (clkspd == 0x00) { // 12 MHz: halve the count
// Adjust high:low /= 2 // Adjust high:low /= 2
} else if (clkspd == 0x10) { // 48 MHz: double the count } else if (clkspd == 0x10) { // 48 MHz: double the count
// Adjust high:low *= 2 // Adjust high:low *= 2
} }
// 24 MHz (0x08): use count as-is // 24 MHz (0x08): use count as-is
while (high:low > 0) { while (high:low > 0) {
wait_TF2(); wait_TF2();
high:low--; high:low--;
} }
} }
``` ```
The pre-DiSEqC delay call is `delay(0, 0x0F)` = 15 ticks x 500 us = **7.5 ms**. This allows the LNB voltage to stabilize before DiSEqC signaling begins. The pre-DiSEqC delay call is `delay(0, 0x0F)` = 15 ticks x 500 us = **7.5 ms**. This allows the LNB voltage to stabilize before DiSEqC signaling begins.
## Complete Timing Summary ## Complete Timing Summary
| Parameter | Value | Source | | Parameter | Value | Source |
|-----------|-------|--------| |-----------|-------|--------|
| Timer2 clock | 4 MHz (48 MHz / 12) | CKCON default, T2M=0 | | Timer2 clock | 4 MHz (48 MHz / 12) | CKCON default, T2M=0 |
| Timer2 reload | `0xF82F` | RCAP2H:RCAP2L | | Timer2 reload | `0xF82F` | RCAP2H:RCAP2L |
| Tick period | 500.25 us | (65536 - 63535) / 4 MHz | | Tick period | 500.25 us | (65536 - 63535) / 4 MHz |
| Bit period | 1.5 ms (3 ticks) | DiSEqC Manchester encoding | | Bit period | 1.5 ms (3 ticks) | DiSEqC Manchester encoding |
| Byte period | 13.5 ms (9 bits) | 8 data + 1 parity | | Byte period | 13.5 ms (9 bits) | 8 data + 1 parity |
| Tone burst duration | 12.5 ms (25 ticks) | Mini-command A/B | | Tone burst duration | 12.5 ms (25 ticks) | Mini-command A/B |
| Pre-TX settling delay | 7.5 ms (15 ticks) | Voltage stabilization | | Pre-TX settling delay | 7.5 ms (15 ticks) | Voltage stabilization |
| Data '0' | 1.0 ms tone + 0.5 ms silence | 2/3 duty cycle | | Data '0' | 1.0 ms tone + 0.5 ms silence | 2/3 duty cycle |
| Data '1' | 0.5 ms tone + 1.0 ms silence | 1/3 duty cycle | | Data '1' | 0.5 ms tone + 1.0 ms silence | 1/3 duty cycle |
| Carrier frequency | 22 kHz (external oscillator) | Gated by P0.3 | | Carrier frequency | 22 kHz (external oscillator) | Gated by P0.3 |
| 3-byte DiSEqC message | ~48 ms total | 7.5 ms settle + 3 x 13.5 ms | | 3-byte DiSEqC message | ~48 ms total | 7.5 ms settle + 3 x 13.5 ms |
| 6-byte DiSEqC message | ~88.5 ms total | 7.5 ms settle + 6 x 13.5 ms | | 6-byte DiSEqC message | ~88.5 ms total | 7.5 ms settle + 6 x 13.5 ms |

View File

@ -1,106 +1,106 @@
--- ---
title: Legacy Dish Network Switch title: Legacy Dish Network Switch
description: SET_DN_SWITCH (0x8F) protocol for Dish Network SW21/SW44 legacy switches. description: SET_DN_SWITCH (0x8F) protocol for Dish Network SW21/SW44 legacy switches.
--- ---
import { Badge, Aside, Steps } from '@astrojs/starlight/components'; import { Badge, Aside, Steps } from '@astrojs/starlight/components';
The SkyWalker-1 supports legacy Dish Network satellite switches (SW21, SW44) through vendor command `0x8F` (`SET_DN_SWITCH`). This protocol predates DiSEqC and uses a simpler serial bit-bang scheme on a shared GPIO pin. The SkyWalker-1 supports legacy Dish Network satellite switches (SW21, SW44) through vendor command `0x8F` (`SET_DN_SWITCH`). This protocol predates DiSEqC and uses a simpler serial bit-bang scheme on a shared GPIO pin.
## Protocol Overview ## Protocol Overview
The legacy Dish Network switch protocol sends a 7-bit serial command via **GPIO P0.4** (the same pin used for LNB voltage selection). The command is bit-banged LSB-first with fixed timing delays. The legacy Dish Network switch protocol sends a 7-bit serial command via **GPIO P0.4** (the same pin used for LNB voltage selection). The command is bit-banged LSB-first with fixed timing delays.
<Aside type="note"> <Aside type="note">
The 8th bit (bit 7, value `0x80`) of the original Dish Network switch command controls LNB voltage polarity and is **not** sent via this protocol. Instead, the kernel driver sends it separately via `SET_LNB_VOLTAGE` (command `0x8B`). This split between data bits and voltage is handled by the `send_legacy_dish_cmd` callback in the kernel driver. The 8th bit (bit 7, value `0x80`) of the original Dish Network switch command controls LNB voltage polarity and is **not** sent via this protocol. Instead, the kernel driver sends it separately via `SET_LNB_VOLTAGE` (command `0x8B`). This split between data bits and voltage is handled by the `send_legacy_dish_cmd` callback in the kernel driver.
</Aside> </Aside>
## USB Command Format ## USB Command Format
``` ```
USB SETUP: USB SETUP:
bmRequestType = 0x40 (vendor, host-to-device) bmRequestType = 0x40 (vendor, host-to-device)
bRequest = 0x8F (SET_DN_SWITCH) bRequest = 0x8F (SET_DN_SWITCH)
wValue = 7-bit switch command (bits 0-6) wValue = 7-bit switch command (bits 0-6)
wIndex = 0x0000 wIndex = 0x0000
wLength = 0 wLength = 0
``` ```
## Bit-Bang Sequence ## Bit-Bang Sequence
The firmware transmits the 7-bit command using the following GPIO sequence: The firmware transmits the 7-bit command using the following GPIO sequence:
<Steps> <Steps>
1. **Start pulse**: Assert P0.4 HIGH, delay approximately 32 CPU cycles (~0.67 us at 48 MHz) 1. **Start pulse**: Assert P0.4 HIGH, delay approximately 32 CPU cycles (~0.67 us at 48 MHz)
2. **Gap**: De-assert P0.4 LOW, delay approximately 8 CPU cycles (~0.17 us at 48 MHz) 2. **Gap**: De-assert P0.4 LOW, delay approximately 8 CPU cycles (~0.17 us at 48 MHz)
3. **Data bits**: Shift out 7 bits LSB-first via P0.4, with approximately 8-cycle delays between each bit transition 3. **Data bits**: Shift out 7 bits LSB-first via P0.4, with approximately 8-cycle delays between each bit transition
4. **End**: P0.4 returns to its previous LNB voltage state 4. **End**: P0.4 returns to its previous LNB voltage state
</Steps> </Steps>
## Switch Position Mapping ## Switch Position Mapping
The legacy protocol supports the SW21 (2-input, 1-output) and SW44 (4-input, 4-output) switches. The 7-bit command encodes the desired input port and satellite selection: The legacy protocol supports the SW21 (2-input, 1-output) and SW44 (4-input, 4-output) switches. The 7-bit command encodes the desired input port and satellite selection:
| Switch Type | Bit Pattern | Function | | Switch Type | Bit Pattern | Function |
|-------------|-------------|----------| |-------------|-------------|----------|
| SW21 | <Badge text="Port A" variant="success" /> `0bxxxxxxx` with port bit = 0 | Select satellite A input | | SW21 | <Badge text="Port A" variant="success" /> `0bxxxxxxx` with port bit = 0 | Select satellite A input |
| SW21 | <Badge text="Port B" variant="note" /> `0bxxxxxxx` with port bit = 1 | Select satellite B input | | SW21 | <Badge text="Port B" variant="note" /> `0bxxxxxxx` with port bit = 1 | Select satellite B input |
| SW44 | Multiple bit fields | Select one of 4 inputs to one of 4 outputs | | SW44 | Multiple bit fields | Select one of 4 inputs to one of 4 outputs |
The exact bit-field layout is proprietary to Dish Network. The kernel driver constructs the command value in `dishnetwork_send_legacy_command()` based on the requested switch position. The exact bit-field layout is proprietary to Dish Network. The kernel driver constructs the command value in `dishnetwork_send_legacy_command()` based on the requested switch position.
## Timing Characteristics ## Timing Characteristics
The legacy switch protocol is significantly simpler and faster than DiSEqC: The legacy switch protocol is significantly simpler and faster than DiSEqC:
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| Start pulse width | ~0.67 us (32 cycles at 48 MHz) | | Start pulse width | ~0.67 us (32 cycles at 48 MHz) |
| Inter-bit gap | ~0.17 us (8 cycles at 48 MHz) | | Inter-bit gap | ~0.17 us (8 cycles at 48 MHz) |
| Total command time | ~5-10 us for 7 bits | | Total command time | ~5-10 us for 7 bits |
| GPIO pin | P0.4 (shared with LNB voltage) | | GPIO pin | P0.4 (shared with LNB voltage) |
<Aside type="caution"> <Aside type="caution">
Because P0.4 is shared between the legacy switch protocol and LNB voltage selection, a switch command briefly disrupts the LNB voltage level. The switch must complete before the voltage is returned to its correct state. The kernel driver handles this coordination automatically. Because P0.4 is shared between the legacy switch protocol and LNB voltage selection, a switch command briefly disrupts the LNB voltage level. The switch must complete before the voltage is returned to its correct state. The kernel driver handles this coordination automatically.
</Aside> </Aside>
## Kernel Driver Integration ## Kernel Driver Integration
The Linux kernel driver implements legacy Dish Network support through a dedicated callback: The Linux kernel driver implements legacy Dish Network support through a dedicated callback:
```c title="Legacy Dish Network command callback" ```c title="Legacy Dish Network command callback"
// Registered as .send_legacy_dish_cmd in dvb_usb_device_properties // Registered as .send_legacy_dish_cmd in dvb_usb_device_properties
static int gp8psk_send_legacy_dish_cmd(struct dvb_frontend *fe, unsigned long cmd) static int gp8psk_send_legacy_dish_cmd(struct dvb_frontend *fe, unsigned long cmd)
{ {
struct dvb_usb_adapter *adap = fe->dvb->priv; struct dvb_usb_adapter *adap = fe->dvb->priv;
struct dvb_usb_device *d = adap->dev; struct dvb_usb_device *d = adap->dev;
// Bit 7 (0x80) controls voltage, sent separately // Bit 7 (0x80) controls voltage, sent separately
gp8psk_usb_out_op(d, SET_LNB_VOLTAGE, (cmd >> 7) & 1, 0, NULL, 0); gp8psk_usb_out_op(d, SET_LNB_VOLTAGE, (cmd >> 7) & 1, 0, NULL, 0);
// Bits 0-6 sent via SET_DN_SWITCH // Bits 0-6 sent via SET_DN_SWITCH
gp8psk_usb_out_op(d, SET_DN_SWITCH, cmd & 0x7F, 0, NULL, 0); gp8psk_usb_out_op(d, SET_DN_SWITCH, cmd & 0x7F, 0, NULL, 0);
return 0; return 0;
} }
``` ```
## Comparison with DiSEqC ## Comparison with DiSEqC
| Feature | Legacy Dish Protocol | DiSEqC 1.0 | | Feature | Legacy Dish Protocol | DiSEqC 1.0 |
|---------|---------------------|------------| |---------|---------------------|------------|
| Standard | Proprietary (Dish Network) | EUTELSAT standard | | Standard | Proprietary (Dish Network) | EUTELSAT standard |
| Encoding | Serial bit-bang, LSB-first | Manchester encoding, MSB-first | | Encoding | Serial bit-bang, LSB-first | Manchester encoding, MSB-first |
| Carrier | None (direct GPIO) | 22 kHz modulated | | Carrier | None (direct GPIO) | 22 kHz modulated |
| Message length | 7 bits | 3-6 bytes (24-54 bits + parity) | | Message length | 7 bits | 3-6 bytes (24-54 bits + parity) |
| Timing | ~5-10 us total | ~48-88 ms total | | Timing | ~5-10 us total | ~48-88 ms total |
| Switch support | SW21, SW44 | DiSEqC 1.0/1.1/1.2 compatible switches | | Switch support | SW21, SW44 | DiSEqC 1.0/1.1/1.2 compatible switches |
| GPIO pin | P0.4 (shared with voltage) | P0.x (data) + P0.3 (carrier) | | GPIO pin | P0.4 (shared with voltage) | P0.x (data) + P0.3 (carrier) |
| Vendor command | `0x8F` | `0x8D` | | Vendor command | `0x8F` | `0x8D` |
For modern satellite installations, DiSEqC is the preferred switch protocol. The legacy Dish Network protocol exists for backward compatibility with older SW21 and SW44 switches commonly found in North American installations. See the [DiSEqC Protocol](/lnb-diseqc/diseqc-protocol/) page for the full DiSEqC implementation. For modern satellite installations, DiSEqC is the preferred switch protocol. The legacy Dish Network protocol exists for backward compatibility with older SW21 and SW44 switches commonly found in North American installations. See the [DiSEqC Protocol](/lnb-diseqc/diseqc-protocol/) page for the full DiSEqC implementation.

View File

@ -1,127 +1,127 @@
--- ---
title: LNB Control title: LNB Control
description: LNB voltage selection (13V/18V), 22 kHz tone generation, extra volt mode, and current limits. description: LNB voltage selection (13V/18V), 22 kHz tone generation, extra volt mode, and current limits.
--- ---
import { Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components'; import { Badge, Aside, Tabs, TabItem } from '@astrojs/starlight/components';
The SkyWalker-1 controls LNB power and band selection through dedicated GPIO pins on the FX2 microcontroller. No I2C transactions are involved in basic LNB control -- voltage and tone are driven directly by port pins. The SkyWalker-1 controls LNB power and band selection through dedicated GPIO pins on the FX2 microcontroller. No I2C transactions are involved in basic LNB control -- voltage and tone are driven directly by port pins.
## LNB Voltage (13V / 18V) ## LNB Voltage (13V / 18V)
LNB voltage selects the polarization of the received signal. It is controlled via **GPIO P0.4** using vendor command `0x8B` (`SET_LNB_VOLTAGE`). LNB voltage selects the polarization of the received signal. It is controlled via **GPIO P0.4** using vendor command `0x8B` (`SET_LNB_VOLTAGE`).
| wValue | Voltage | GPIO P0.4 | Polarization | | wValue | Voltage | GPIO P0.4 | Polarization |
|--------|---------|-----------|--------------| |--------|---------|-----------|--------------|
| `0x00` | 13V | LOW | Vertical / Circular-Right | | `0x00` | 13V | LOW | Vertical / Circular-Right |
| `0x01` | 18V | HIGH | Horizontal / Circular-Left | | `0x01` | 18V | HIGH | Horizontal / Circular-Left |
The Linux kernel driver sets the voltage during the tuning sequence based on the requested polarization: The Linux kernel driver sets the voltage during the tuning sequence based on the requested polarization:
```c title="Kernel driver polarization mapping" ```c title="Kernel driver polarization mapping"
// From gp8psk-fe.c set_voltage callback // From gp8psk-fe.c set_voltage callback
case SEC_VOLTAGE_13: // Vertical / Circular-R case SEC_VOLTAGE_13: // Vertical / Circular-R
gp8psk_usb_out_op(d, SET_LNB_VOLTAGE, 0, 0, NULL, 0); gp8psk_usb_out_op(d, SET_LNB_VOLTAGE, 0, 0, NULL, 0);
break; break;
case SEC_VOLTAGE_18: // Horizontal / Circular-L case SEC_VOLTAGE_18: // Horizontal / Circular-L
gp8psk_usb_out_op(d, SET_LNB_VOLTAGE, 1, 0, NULL, 0); gp8psk_usb_out_op(d, SET_LNB_VOLTAGE, 1, 0, NULL, 0);
break; break;
``` ```
The configuration status byte (returned by `GET_8PSK_CONFIG`, command `0x80`) reflects the current voltage selection in **bit 5** (`0x20`, `bmSEL18V`). The configuration status byte (returned by `GET_8PSK_CONFIG`, command `0x80`) reflects the current voltage selection in **bit 5** (`0x20`, `bmSEL18V`).
## Extra Volt Mode (+1V Boost) ## Extra Volt Mode (+1V Boost)
For long cable runs where voltage drop is significant, the SkyWalker-1 supports a +1V boost mode (13V becomes 14V, 18V becomes 19V). This is controlled via vendor command `0x94` (`USE_EXTRA_VOLT`). For long cable runs where voltage drop is significant, the SkyWalker-1 supports a +1V boost mode (13V becomes 14V, 18V becomes 19V). This is controlled via vendor command `0x94` (`USE_EXTRA_VOLT`).
| wValue | XRAM 0xE0B6 | Result | | wValue | XRAM 0xE0B6 | Result |
|--------|-------------|--------| |--------|-------------|--------|
| `0x00` | `0x62` | Normal voltage (13V / 18V) | | `0x00` | `0x62` | Normal voltage (13V / 18V) |
| `0x01` | `0x6A` | Boosted voltage (14V / 19V) | | `0x01` | `0x6A` | Boosted voltage (14V / 19V) |
The difference between the two XRAM values is **bit 3** (`0x08`), which enables the boost on the LNB power regulator circuitry. The difference between the two XRAM values is **bit 3** (`0x08`), which enables the boost on the LNB power regulator circuitry.
<Aside type="caution"> <Aside type="caution">
The LNB power output has firm current limits. The maximum **non-continuous** draw is 750 mA (for short bursts of several minutes). For permanent continuous load, do not exceed **450 mA** to avoid overheating the onboard regulator. Exceeding these limits risks thermal damage to the SkyWalker-1 board. The LNB power output has firm current limits. The maximum **non-continuous** draw is 750 mA (for short bursts of several minutes). For permanent continuous load, do not exceed **450 mA** to avoid overheating the onboard regulator. Exceeding these limits risks thermal damage to the SkyWalker-1 board.
</Aside> </Aside>
The kernel driver exposes extra volt mode through the `enable_high_lnb_voltage` callback in the DVB frontend properties. The kernel driver exposes extra volt mode through the `enable_high_lnb_voltage` callback in the DVB frontend properties.
## 22 kHz Tone Generation ## 22 kHz Tone Generation
The 22 kHz tone selects the high or low band on a universal LNB. It is controlled via **GPIO P0.3** using vendor command `0x8C` (`SET_22KHZ_TONE`). The 22 kHz tone selects the high or low band on a universal LNB. It is controlled via **GPIO P0.3** using vendor command `0x8C` (`SET_22KHZ_TONE`).
| wValue | State | GPIO P0.3 | LNB Band | | wValue | State | GPIO P0.3 | LNB Band |
|--------|-------|-----------|----------| |--------|-------|-----------|----------|
| `0x00` | OFF | LOW | Low band (9.75 GHz LO on universal LNB) | | `0x00` | OFF | LOW | Low band (9.75 GHz LO on universal LNB) |
| `0x01` | ON | HIGH | High band (10.6 GHz LO on universal LNB) | | `0x01` | ON | HIGH | High band (10.6 GHz LO on universal LNB) |
<Aside type="note"> <Aside type="note">
P0.3 does not generate the 22 kHz carrier directly. Instead, it **gates an external 22 kHz oscillator circuit** on the PCB. When P0.3 is HIGH, the oscillator output is coupled onto the coaxial cable's DC power line alongside the 13V/18V LNB voltage. When P0.3 is LOW, the oscillator is disabled and no tone is present. P0.3 does not generate the 22 kHz carrier directly. Instead, it **gates an external 22 kHz oscillator circuit** on the PCB. When P0.3 is HIGH, the oscillator output is coupled onto the coaxial cable's DC power line alongside the 13V/18V LNB voltage. When P0.3 is LOW, the oscillator is disabled and no tone is present.
</Aside> </Aside>
The configuration status byte tracks the tone state in **bit 4** (`0x10`, `bm22kHz`). The configuration status byte tracks the tone state in **bit 4** (`0x10`, `bm22kHz`).
## LNB Power Supply Enable ## LNB Power Supply Enable
Before any LNB control is possible, the LNB power supply itself must be enabled via vendor command `0x8A` (`START_INTERSIL`). The kernel driver does this during the boot sequence if bit 2 (`bmIntersilOn`) of the configuration status byte is not already set. Before any LNB control is possible, the LNB power supply itself must be enabled via vendor command `0x8A` (`START_INTERSIL`). The kernel driver does this during the boot sequence if bit 2 (`bmIntersilOn`) of the configuration status byte is not already set.
| wValue | Action | Config Bit | | wValue | Action | Config Bit |
|--------|--------|------------| |--------|--------|------------|
| `0x01` | Enable LNB power supply | Sets `bmIntersilOn` (bit 2) | | `0x01` | Enable LNB power supply | Sets `bmIntersilOn` (bit 2) |
| `0x00` | Disable LNB power supply | Clears `bmIntersilOn` (bit 2) | | `0x00` | Disable LNB power supply | Clears `bmIntersilOn` (bit 2) |
In the custom v3.01.0 firmware, enabling the LNB supply also configures the output enable masks for the LNB control GPIO pins: In the custom v3.01.0 firmware, enabling the LNB supply also configures the output enable masks for the LNB control GPIO pins:
```c title="START_INTERSIL handler in custom firmware" ```c title="START_INTERSIL handler in custom firmware"
case START_INTERSIL: case START_INTERSIL:
if (wval) { if (wval) {
OEA |= (PIN_22KHZ | PIN_LNB_VOLT | PIN_DISEQC); OEA |= (PIN_22KHZ | PIN_LNB_VOLT | PIN_DISEQC);
config_status |= BM_INTERSIL; config_status |= BM_INTERSIL;
} else { } else {
config_status &= ~BM_INTERSIL; config_status &= ~BM_INTERSIL;
} }
``` ```
## GPIO Pin Assignments ## GPIO Pin Assignments
The LNB control pins are consistent across firmware versions, though their exact initialization differs: The LNB control pins are consistent across firmware versions, though their exact initialization differs:
| GPIO Pin | Function | Direction | Init State | | GPIO Pin | Function | Direction | Init State |
|----------|----------|-----------|------------| |----------|----------|-----------|------------|
| P0.1 | Power supply enable | Output | LOW (off) | | P0.1 | Power supply enable | Output | LOW (off) |
| P0.2 | Power supply disable | Output | HIGH (active disable) | | P0.2 | Power supply disable | Output | HIGH (active disable) |
| P0.3 | 22 kHz tone gate | Output | LOW (tone off) | | P0.3 | 22 kHz tone gate | Output | LOW (tone off) |
| P0.4 | LNB voltage select | Output | LOW (13V) | | P0.4 | LNB voltage select | Output | LOW (13V) |
| P0.5 | BCM4500 hardware reset | Output | LOW (reset asserted) | | P0.5 | BCM4500 hardware reset | Output | LOW (reset asserted) |
The initial GPIO state after power-on is `IOA = 0x84` (P0.7 and P0.2 HIGH, all others LOW), with the output enable mask `OEA = 0xBE` (P0.1 through P0.5 and P0.7 as outputs). The initial GPIO state after power-on is `IOA = 0x84` (P0.7 and P0.2 HIGH, all others LOW), with the output enable mask `OEA = 0xBE` (P0.1 through P0.5 and P0.7 as outputs).
## LNB GPIO Debug Commands ## LNB GPIO Debug Commands
Three vendor commands provide low-level GPIO access for LNB debugging: Three vendor commands provide low-level GPIO access for LNB debugging:
| Command | Name | Purpose | | Command | Name | Purpose |
|---------|------|---------| |---------|------|---------|
| `0x96` | `SET_LNB_GPIO_MODE` | Configure LNB GPIO output enables | | `0x96` | `SET_LNB_GPIO_MODE` | Configure LNB GPIO output enables |
| `0x97` | `SET_GPIO_PINS` | Direct write to LNB GPIO pins via `wValue` bitmap | | `0x97` | `SET_GPIO_PINS` | Direct write to LNB GPIO pins via `wValue` bitmap |
| `0x98` | `GET_GPIO_STATUS` | Read LNB feedback GPIO pin (1 byte) | | `0x98` | `GET_GPIO_STATUS` | Read LNB feedback GPIO pin (1 byte) |
These commands access Port B (XRAM-mapped IOB) rather than Port A. In v2.06 and v2.13, `0x97` controls IOB bits 1 and 2 for LNB, while `0x96` configures IOB bit 3 as the GPIO mode select. Rev.2 uses IOB bit 4 instead. These commands access Port B (XRAM-mapped IOB) rather than Port A. In v2.06 and v2.13, `0x97` controls IOB bits 1 and 2 for LNB, while `0x96` configures IOB bit 3 as the GPIO mode select. Rev.2 uses IOB bit 4 instead.
<Aside type="note"> <Aside type="note">
These debug GPIO commands are not used by the Linux kernel driver during normal operation. They are available for diagnostic tools and custom applications that need direct hardware-level LNB control. These debug GPIO commands are not used by the Linux kernel driver during normal operation. They are available for diagnostic tools and custom applications that need direct hardware-level LNB control.
</Aside> </Aside>
## Complete LNB Configuration Sequence ## Complete LNB Configuration Sequence
During a typical tune operation, the kernel driver configures the LNB in this order: During a typical tune operation, the kernel driver configures the LNB in this order:
``` ```
1. SET_LNB_VOLTAGE (0x8B) -- Select 13V or 18V based on polarization 1. SET_LNB_VOLTAGE (0x8B) -- Select 13V or 18V based on polarization
2. SET_22KHZ_TONE (0x8C) -- Select low or high band 2. SET_22KHZ_TONE (0x8C) -- Select low or high band
3. SEND_DISEQC (0x8D) -- Switch multi-port switch if needed 3. SEND_DISEQC (0x8D) -- Switch multi-port switch if needed
4. TUNE_8PSK (0x86) -- Send tuning parameters 4. TUNE_8PSK (0x86) -- Send tuning parameters
``` ```
The voltage and tone are set before any DiSEqC commands because the LNB must be powered and in the correct band before the switch can respond. See the [DiSEqC Protocol](/lnb-diseqc/diseqc-protocol/) page for details on switch control, and the [Tuning Protocol](/bcm4500/tuning-protocol/) for the complete tune flow. The voltage and tone are set before any DiSEqC commands because the LNB must be powered and in the correct band before the switch can respond. See the [DiSEqC Protocol](/lnb-diseqc/diseqc-protocol/) page for details on switch control, and the [Tuning Protocol](/bcm4500/tuning-protocol/) for the complete tune flow.

View File

@ -1,65 +1,65 @@
--- ---
title: Sources title: Sources
description: Primary sources, analysis documents, and community references for the SkyWalker-1 reverse engineering project. description: Primary sources, analysis documents, and community references for the SkyWalker-1 reverse engineering project.
--- ---
# Sources and Bibliography # Sources and Bibliography
All technical content in this documentation was derived from the following primary sources. No public BCM4500 datasheet with complete register definitions exists; register addresses, functions, and protocols were determined through firmware disassembly, I2C bus captures, driver source analysis, and behavioral testing. All technical content in this documentation was derived from the following primary sources. No public BCM4500 datasheet with complete register definitions exists; register addresses, functions, and protocols were determined through firmware disassembly, I2C bus captures, driver source analysis, and behavioral testing.
--- ---
## Firmware Analysis ## Firmware Analysis
Five firmware images were decompiled and disassembled using Ghidra (8051 processor module): Five firmware images were decompiled and disassembled using Ghidra (8051 processor module):
| Firmware | Ghidra Port | Source | | Firmware | Ghidra Port | Source |
|----------|-------------|--------| |----------|-------------|--------|
| v2.06.04 | 8193 | Extracted from SkyWalker-1 EEPROM via `eeprom_dump.py` | | v2.06.04 | 8193 | Extracted from SkyWalker-1 EEPROM via `eeprom_dump.py` |
| Rev.2 v2.10.04 | 8197 | Extracted from Rev.2 hardware EEPROM | | Rev.2 v2.10.04 | 8197 | Extracted from Rev.2 hardware EEPROM |
| v2.13.01 (FW1) | 8194 | Extracted from `SW1_update_2_13_x.exe` via `wine_memdump.py` | | v2.13.01 (FW1) | 8194 | Extracted from `SW1_update_2_13_x.exe` via `wine_memdump.py` |
| v2.13.02 (FW2) | 8195 | Extracted from `SW1_update_2_13_x.exe` via `wine_memdump.py` | | v2.13.02 (FW2) | 8195 | Extracted from `SW1_update_2_13_x.exe` via `wine_memdump.py` |
| v2.13.03 (FW3) | 8196 | Extracted from `SW1_update_2_13_x.exe` via `wine_memdump.py` | | v2.13.03 (FW3) | 8196 | Extracted from `SW1_update_2_13_x.exe` via `wine_memdump.py` |
Binary dumps are in `firmware-dump/`. Binary dumps are in `firmware-dump/`.
## Driver Source ## Driver Source
| Source | Path / Location | | Source | Path / Location |
|--------|----------------| |--------|----------------|
| Linux kernel 6.16.5 | `drivers/media/usb/dvb-usb/gp8psk.c`, `gp8psk.h`, `gp8psk-fe.c`, `gp8psk-fe.h` | | Linux kernel 6.16.5 | `drivers/media/usb/dvb-usb/gp8psk.c`, `gp8psk.h`, `gp8psk-fe.c`, `gp8psk-fe.h` |
| Linux kernel | `drivers/media/usb/dvb-usb/dvb-usb-firmware.c` | | Linux kernel | `drivers/media/usb/dvb-usb/dvb-usb-firmware.c` |
| Windows BDA driver | `SkyWalker1_Final_Release/Source/SkyWalker1Control.cpp` | | Windows BDA driver | `SkyWalker1_Final_Release/Source/SkyWalker1Control.cpp` |
| Windows BDA driver | `SkyWalker1_Final_Release/Include/SkyWalker1Control.h`, `SkyWalker1CommonDef.h` | | Windows BDA driver | `SkyWalker1_Final_Release/Include/SkyWalker1Control.h`, `SkyWalker1CommonDef.h` |
## Hardware Documentation ## Hardware Documentation
- BCM4500 Datasheet: [DatasheetQ](https://html.datasheetq.com/pdf-html/885700/Broadcom/2page/BCM4500.html), [Elcodis](https://elcodis.com/parts/5786421/BCM4500.html) - BCM4500 Datasheet: [DatasheetQ](https://html.datasheetq.com/pdf-html/885700/Broadcom/2page/BCM4500.html), [Elcodis](https://elcodis.com/parts/5786421/BCM4500.html)
- BCM4501 Product Page: [Broadcom](https://www.broadcom.com/products/broadband/set-top-box/bcm4501) - BCM4501 Product Page: [Broadcom](https://www.broadcom.com/products/broadband/set-top-box/bcm4501)
- Cypress CY7C68013A (FX2LP) Technical Reference Manual - Cypress CY7C68013A (FX2LP) Technical Reference Manual
- Genpix Electronics: https://www.genpix-electronics.com/index.php?act=viewDoc&docId=9 - Genpix Electronics: https://www.genpix-electronics.com/index.php?act=viewDoc&docId=9
- Genpix SkyWalker-3 specifications: https://www.genpix-electronics.com/what-is-skywalker-3.html - Genpix SkyWalker-3 specifications: https://www.genpix-electronics.com/what-is-skywalker-3.html
- Device `dmesg` output from running SkyWalker-1 hardware - Device `dmesg` output from running SkyWalker-1 hardware
## Analysis Reports ## Analysis Reports
Internal analysis documents produced during this project (in `docs/` directory): Internal analysis documents produced during this project (in `docs/` directory):
1. `gp8psk-driver-analysis.md` -- Linux kernel driver analysis 1. `gp8psk-driver-analysis.md` -- Linux kernel driver analysis
2. `firmware-analysis-v206-vs-v213.md` -- v2.06 vs v2.13 firmware comparison 2. `firmware-analysis-v206-vs-v213.md` -- v2.06 vs v2.13 firmware comparison
3. `rev2-deep-analysis.md` -- Rev.2 deep function inventory (107 functions) 3. `rev2-deep-analysis.md` -- Rev.2 deep function inventory (107 functions)
4. `gpif-streaming-analysis.md` -- GPIF/MPEG-2 streaming path 4. `gpif-streaming-analysis.md` -- GPIF/MPEG-2 streaming path
5. `tuning-protocol-analysis.md` -- TUNE_8PSK protocol deep dive 5. `tuning-protocol-analysis.md` -- TUNE_8PSK protocol deep dive
6. `vendor-commands-unknown.md` -- Vendor command decode (0x8F, 0x91--0x98) 6. `vendor-commands-unknown.md` -- Vendor command decode (0x8F, 0x91--0x98)
7. `kernel-fw01-analysis.md` -- Kernel firmware format and EEPROM boot 7. `kernel-fw01-analysis.md` -- Kernel firmware format and EEPROM boot
8. `firmware-dump/fw_v213_comparison_report.md` -- v2.13 sub-variant comparison 8. `firmware-dump/fw_v213_comparison_report.md` -- v2.13 sub-variant comparison
9. `dvb-s2-investigation.md` -- DVB-S2 incompatibility investigation 9. `dvb-s2-investigation.md` -- DVB-S2 incompatibility investigation
10. `docs/boot-debug-findings.md` -- Boot/I2C debugging findings 10. `docs/boot-debug-findings.md` -- Boot/I2C debugging findings
11. `docs/diseqc/diseqc-skywalker-1.md` -- DiSEqC Windows BDA interface 11. `docs/diseqc/diseqc-skywalker-1.md` -- DiSEqC Windows BDA interface
12. `firmware/skywalker1.c` -- Custom firmware v3.01.0 source 12. `firmware/skywalker1.c` -- Custom firmware v3.01.0 source
## Community References ## Community References
- [LinuxTV mailing list: BCM4500 and DVB-S2](https://www.mail-archive.com/linux-dvb@linuxtv.org/msg24808.html) - [LinuxTV mailing list: BCM4500 and DVB-S2](https://www.mail-archive.com/linux-dvb@linuxtv.org/msg24808.html)
- [SatelliteGuys: Turbo 8PSK card reverse engineering](https://www.satelliteguys.us/xen/threads/another-turbo-8psk-card.246879/) - [SatelliteGuys: Turbo 8PSK card reverse engineering](https://www.satelliteguys.us/xen/threads/another-turbo-8psk-card.246879/)
- [SatelliteGuys: Genpix SkyWalker-1 discussion](https://www.satelliteguys.us/xen/threads/genpix-skywalker-1.214196/) - [SatelliteGuys: Genpix SkyWalker-1 discussion](https://www.satelliteguys.us/xen/threads/genpix-skywalker-1.214196/)

View File

@ -1,95 +1,95 @@
--- ---
title: Arc Survey title: Arc Survey
description: Automated multi-satellite orbital arc survey with motor control and carrier catalog aggregation. description: Automated multi-satellite orbital arc survey with motor control and carrier catalog aggregation.
--- ---
import { Aside, Steps } from '@astrojs/starlight/components'; import { Aside, Steps } from '@astrojs/starlight/components';
The `arc_survey.py` tool automates a complete satellite census across the GEO orbital arc. The `arc_survey.py` tool automates a complete satellite census across the GEO orbital arc.
It points the dish motor to each orbital longitude, runs a full six-stage carrier survey, It points the dish motor to each orbital longitude, runs a full six-stage carrier survey,
saves individual catalogs, and produces an aggregated sky map. saves individual catalogs, and produces an aggregated sky map.
## Quick Start ## Quick Start
```bash ```bash
# Survey 4 specific North American slots # Survey 4 specific North American slots
python tools/arc_survey.py --observer-lon -96.8 --slots "97W,99W,101W,103W" python tools/arc_survey.py --observer-lon -96.8 --slots "97W,99W,101W,103W"
# Survey a 60-degree arc at 3-degree intervals # Survey a 60-degree arc at 3-degree intervals
python tools/arc_survey.py --observer-lon -96.8 --arc -120 -60 --step 3 python tools/arc_survey.py --observer-lon -96.8 --arc -120 -60 --step 3
# List common NA orbital positions # List common NA orbital positions
python tools/arc_survey.py --list-slots python tools/arc_survey.py --list-slots
``` ```
## How It Works ## How It Works
<Steps> <Steps>
1. **Parse orbital slot list** from CLI, JSON file, or arc range 1. **Parse orbital slot list** from CLI, JSON file, or arc range
2. **For each slot**: send USALS GotoX command to motor 2. **For each slot**: send USALS GotoX command to motor
3. **Wait for settle** (scales with angular distance, minimum 15 seconds) 3. **Wait for settle** (scales with angular distance, minimum 15 seconds)
4. **Run six-stage survey**: coarse sweep → peak detection → fine sweep → blind scan → TS sample → catalog 4. **Run six-stage survey**: coarse sweep → peak detection → fine sweep → blind scan → TS sample → catalog
5. **Save per-slot catalog** to `~/.skywalker1/surveys/` 5. **Save per-slot catalog** to `~/.skywalker1/surveys/`
6. **Save arc survey state** to `~/.skywalker1/arc-surveys/` (for resume) 6. **Save arc survey state** to `~/.skywalker1/arc-surveys/` (for resume)
7. **Print aggregated summary** with per-slot carrier counts 7. **Print aggregated summary** with per-slot carrier counts
</Steps> </Steps>
## Resume Support ## Resume Support
The tool saves state after every completed slot. If interrupted (Ctrl-C, power loss, etc.): The tool saves state after every completed slot. If interrupted (Ctrl-C, power loss, etc.):
```bash ```bash
python tools/arc_survey.py --resume ~/.skywalker1/arc-surveys/arc-survey-2026-02-17.json python tools/arc_survey.py --resume ~/.skywalker1/arc-surveys/arc-survey-2026-02-17.json
``` ```
Already-surveyed slots are skipped. The survey continues from where it left off. Already-surveyed slots are skipped. The survey continues from where it left off.
## Slot Specification ## Slot Specification
<Aside type="tip" title="Slot formats"> <Aside type="tip" title="Slot formats">
Slots accept multiple formats: `97W`, `97.5W`, `3E`, `-97`, `-97.5` Slots accept multiple formats: `97W`, `97.5W`, `3E`, `-97`, `-97.5`
</Aside> </Aside>
**CLI list:** **CLI list:**
```bash ```bash
--slots "97W,99W,101W,103W,105W" --slots "97W,99W,101W,103W,105W"
``` ```
**JSON file:** **JSON file:**
```json ```json
[ [
{"name": "97W", "lon": -97.0}, {"name": "97W", "lon": -97.0},
{"name": "99W", "lon": -99.0}, {"name": "99W", "lon": -99.0},
{"name": "Galaxy 16", "lon": -99.0} {"name": "Galaxy 16", "lon": -99.0}
] ]
``` ```
**Arc range:** **Arc range:**
```bash ```bash
--arc -120 -60 --step 3 --arc -120 -60 --step 3
``` ```
## Options ## Options
| Flag | Default | Description | | Flag | Default | Description |
|---|---|---| |---|---|---|
| `--observer-lon` | (required) | Observer longitude (negative = west) | | `--observer-lon` | (required) | Observer longitude (negative = west) |
| `--observer-lat` | 0.0 | Observer latitude | | `--observer-lat` | 0.0 | Observer latitude |
| `--slots` | — | Comma-separated slot list | | `--slots` | — | Comma-separated slot list |
| `--file` | — | JSON file with slot definitions | | `--file` | — | JSON file with slot definitions |
| `--arc` | — | Start/stop longitude for range scan | | `--arc` | — | Start/stop longitude for range scan |
| `--step` | 3.0 | Degrees between arc positions | | `--step` | 3.0 | Degrees between arc positions |
| `--coarse-step` | 5.0 | MHz step for coarse spectrum sweep | | `--coarse-step` | 5.0 | MHz step for coarse spectrum sweep |
| `--settle-time` | 15 | Minimum motor settle time (seconds) | | `--settle-time` | 15 | Minimum motor settle time (seconds) |
| `--resume` | — | Resume from saved state file | | `--resume` | — | Resume from saved state file |
| `--list-slots` | — | Print common NA slots and exit | | `--list-slots` | — | Print common NA slots and exit |
## Output Files ## Output Files
| Location | Content | | Location | Content |
|---|---| |---|---|
| `~/.skywalker1/surveys/arc-DATE-SLOT.json` | Per-slot carrier catalog | | `~/.skywalker1/surveys/arc-DATE-SLOT.json` | Per-slot carrier catalog |
| `~/.skywalker1/arc-surveys/arc-survey-DATE.json` | Arc survey state (for resume) | | `~/.skywalker1/arc-surveys/arc-survey-DATE.json` | Arc survey state (for resume) |
The per-slot catalogs are standard `CarrierCatalog` JSON files, compatible with The per-slot catalogs are standard `CarrierCatalog` JSON files, compatible with
the diff and comparison tools in `carrier_catalog.py`. the diff and comparison tools in `carrier_catalog.py`.

View File

@ -1,75 +1,75 @@
--- ---
title: Beacon Logger title: Beacon Logger
description: Long-term satellite signal logging for propagation research, rain fade analysis, and link budget validation. description: Long-term satellite signal logging for propagation research, rain fade analysis, and link budget validation.
--- ---
import { Aside, Steps } from '@astrojs/starlight/components'; import { Aside, Steps } from '@astrojs/starlight/components';
The `beacon_logger.py` tool locks onto a stable satellite transponder and records SNR, AGC levels, The `beacon_logger.py` tool locks onto a stable satellite transponder and records SNR, AGC levels,
and signal power at configurable intervals. Multi-day datasets reveal rain fade events, diurnal and signal power at configurable intervals. Multi-day datasets reveal rain fade events, diurnal
thermal effects, antenna mount drift, and LNB gain variations. thermal effects, antenna mount drift, and LNB gain variations.
## Quick Start ## Quick Start
```bash ```bash
# Log a Ku-band transponder for 1 hour, CSV output # Log a Ku-band transponder for 1 hour, CSV output
python tools/beacon_logger.py --freq 1265000 --sr 20000000 --output beacon.csv python tools/beacon_logger.py --freq 1265000 --sr 20000000 --output beacon.csv
# 24-hour unattended logging with per-minute statistics # 24-hour unattended logging with per-minute statistics
python tools/beacon_logger.py --freq 1265000 --sr 20000000 \ python tools/beacon_logger.py --freq 1265000 --sr 20000000 \
--output beacon-24h.csv --json-output stats.jsonl --duration 86400 --output beacon-24h.csv --json-output stats.jsonl --duration 86400
``` ```
<Aside type="note" title="Frequency units"> <Aside type="note" title="Frequency units">
The `--freq` parameter is in **kHz** (IF frequency). For a Ku-band transponder at 12015 MHz The `--freq` parameter is in **kHz** (IF frequency). For a Ku-band transponder at 12015 MHz
with a universal LNB at LO 10750 MHz, the IF is 12015 10750 = 1265 MHz = **1265000 kHz**. with a universal LNB at LO 10750 MHz, the IF is 12015 10750 = 1265 MHz = **1265000 kHz**.
</Aside> </Aside>
## Features ## Features
- **Auto-relock**: If signal is lost (weather, dish movement), automatically retunes and relocks - **Auto-relock**: If signal is lost (weather, dish movement), automatically retunes and relocks
- **Statistics per interval**: min/max/mean/stddev of SNR over each reporting window - **Statistics per interval**: min/max/mean/stddev of SNR over each reporting window
- **Dual output**: Raw per-sample CSV + per-interval JSONL statistics - **Dual output**: Raw per-sample CSV + per-interval JSONL statistics
- **Signal handlers**: Clean shutdown on SIGTERM/SIGINT, no data loss - **Signal handlers**: Clean shutdown on SIGTERM/SIGINT, no data loss
- **Systemd integration**: `--generate-systemd` prints a ready-to-use unit file - **Systemd integration**: `--generate-systemd` prints a ready-to-use unit file
## Options ## Options
| Flag | Default | Description | | Flag | Default | Description |
|---|---|---| |---|---|---|
| `--freq` | (required) | IF frequency in kHz | | `--freq` | (required) | IF frequency in kHz |
| `--sr` | 20000000 | Symbol rate in sps | | `--sr` | 20000000 | Symbol rate in sps |
| `--mod` | qpsk | Modulation type | | `--mod` | qpsk | Modulation type |
| `--fec` | auto | FEC rate | | `--fec` | auto | FEC rate |
| `--output` | — | CSV output file (raw samples) | | `--output` | — | CSV output file (raw samples) |
| `--json-output` | — | JSONL file (per-interval statistics) | | `--json-output` | — | JSONL file (per-interval statistics) |
| `--duration` | 3600 | Logging duration in seconds | | `--duration` | 3600 | Logging duration in seconds |
| `--sample-interval` | 1.0 | Seconds between samples | | `--sample-interval` | 1.0 | Seconds between samples |
| `--report-interval` | 60 | Seconds between summary reports | | `--report-interval` | 60 | Seconds between summary reports |
| `--pol` | — | LNB polarization (H/V) | | `--pol` | — | LNB polarization (H/V) |
| `--band` | — | LNB band (low/high) | | `--band` | — | LNB band (low/high) |
| `--daemon` | — | Suppress stdout for background operation | | `--daemon` | — | Suppress stdout for background operation |
| `--generate-systemd` | — | Print systemd unit file and exit | | `--generate-systemd` | — | Print systemd unit file and exit |
## Systemd Daemon Mode ## Systemd Daemon Mode
```bash ```bash
# Generate and install the service # Generate and install the service
python tools/beacon_logger.py --generate-systemd \ python tools/beacon_logger.py --generate-systemd \
--freq 1265000 --sr 20000000 \ --freq 1265000 --sr 20000000 \
--output /var/log/skywalker/beacon.csv \ --output /var/log/skywalker/beacon.csv \
--duration 999999 > /tmp/beacon-logger.service --duration 999999 > /tmp/beacon-logger.service
sudo cp /tmp/beacon-logger.service /etc/systemd/system/ sudo cp /tmp/beacon-logger.service /etc/systemd/system/
sudo systemctl enable --now beacon-logger sudo systemctl enable --now beacon-logger
``` ```
## Applications ## Applications
| Use Case | What to Measure | Interval | | Use Case | What to Measure | Interval |
|---|---|---| |---|---|---|
| Rain fade | SNR drops during precipitation | 1 Hz | | Rain fade | SNR drops during precipitation | 1 Hz |
| LNB thermal drift | AGC shift over temperature cycle | 10s | | LNB thermal drift | AGC shift over temperature cycle | 10s |
| Antenna mount stability | Slow SNR decay over days | 60s | | Antenna mount stability | Slow SNR decay over days | 60s |
| Link budget validation | Long-term average vs. predicted | 60s | | Link budget validation | Long-term average vs. predicted | 60s |
| Ionospheric scintillation | Rapid AGC fluctuations | 1 Hz | | Ionospheric scintillation | Rapid AGC fluctuations | 1 Hz |

View File

@ -1,259 +1,259 @@
--- ---
title: Debugging Tools title: Debugging Tools
description: Hardware diagnostic tools for boot testing, I2C bus debugging, and firmware extraction. description: Hardware diagnostic tools for boot testing, I2C bus debugging, and firmware extraction.
--- ---
import { Tabs, TabItem, Steps, Aside, Badge } from '@astrojs/starlight/components'; import { Tabs, TabItem, Steps, Aside, Badge } from '@astrojs/starlight/components';
The `tools/` directory includes a suite of diagnostic scripts developed during the reverse engineering of the SkyWalker-1. These tools were instrumental in isolating the I2C STOP corruption bug in the FX2 controller and verifying correct BCM4500 initialization. The `tools/` directory includes a suite of diagnostic scripts developed during the reverse engineering of the SkyWalker-1. These tools were instrumental in isolating the I2C STOP corruption bug in the FX2 controller and verifying correct BCM4500 initialization.
All debugging tools require `pyusb`, root access, and the kernel `dvb_usb_gp8psk` module to be unloaded. All debugging tools require `pyusb`, root access, and the kernel `dvb_usb_gp8psk` module to be unloaded.
```bash ```bash
pip install pyusb pip install pyusb
sudo modprobe -r dvb_usb_gp8psk gp8psk_fe sudo modprobe -r dvb_usb_gp8psk gp8psk_fe
``` ```
<Tabs> <Tabs>
<TabItem label="Boot Tests"> <TabItem label="Boot Tests">
## Boot Testing Tools ## Boot Testing Tools
Two scripts test the BCM4500 boot sequence using debug modes in the custom v3.01.0 firmware. Two scripts test the BCM4500 boot sequence using debug modes in the custom v3.01.0 firmware.
### test_boot.py -- Full Boot Verification ### test_boot.py -- Full Boot Verification
Runs a complete BOOT_8PSK sequence and reports success or failure with detailed register readback. Runs a complete BOOT_8PSK sequence and reports success or failure with detailed register readback.
```bash ```bash
sudo python3 tools/test_boot.py sudo python3 tools/test_boot.py
``` ```
**What it does:** **What it does:**
<Steps> <Steps>
1. Reads firmware version via `GET_FW_VERS` (0x92) 1. Reads firmware version via `GET_FW_VERS` (0x92)
2. Reads config status via `GET_8PSK_CONFIG` (0x80) 2. Reads config status via `GET_8PSK_CONFIG` (0x80)
3. Sends `BOOT_8PSK` (0x89, wValue=1) with a 10-second timeout 3. Sends `BOOT_8PSK` (0x89, wValue=1) with a 10-second timeout
4. Decodes the 3-byte response: config status, boot stage, probe byte 4. Decodes the 3-byte response: config status, boot stage, probe byte
5. On success: reads BCM4500 direct registers (0xA2--0xA8), indirect registers (pages 0x00--0x0F), I2C diagnostic data, signal strength, and lock status 5. On success: reads BCM4500 direct registers (0xA2--0xA8), indirect registers (pages 0x00--0x0F), I2C diagnostic data, signal strength, and lock status
6. On failure: runs I2C bus scan (0xB4), attempts raw I2C reads to BCM4500 6. On failure: runs I2C bus scan (0xB4), attempts raw I2C reads to BCM4500
</Steps> </Steps>
**Boot stage codes:** **Boot stage codes:**
| Stage | Code | Meaning | | Stage | Code | Meaning |
|-------|------|---------| |-------|------|---------|
| `NOT_STARTED` | 0x00 | Boot not attempted | | `NOT_STARTED` | 0x00 | Boot not attempted |
| `GPIO_SETUP` | 0x01 | GPIO pins configured | | `GPIO_SETUP` | 0x01 | GPIO pins configured |
| `PWR_SETTLED` | 0x02 | Power-on delay complete | | `PWR_SETTLED` | 0x02 | Power-on delay complete |
| `I2C_PROBE` | 0x03 | Probing BCM4500 on I2C | | `I2C_PROBE` | 0x03 | Probing BCM4500 on I2C |
| `INIT_BLK0` | 0x04 | Writing init block 0 | | `INIT_BLK0` | 0x04 | Writing init block 0 |
| `INIT_BLK1` | 0x05 | Writing init block 1 | | `INIT_BLK1` | 0x05 | Writing init block 1 |
| `INIT_BLK2` | 0x06 | Writing init block 2 | | `INIT_BLK2` | 0x06 | Writing init block 2 |
| `COMPLETE` | 0xFF | Boot finished | | `COMPLETE` | 0xFF | Boot finished |
**Config status flags after successful boot:** **Config status flags after successful boot:**
| Flag | Bit | Expected | | Flag | Bit | Expected |
|------|-----|----------| |------|-----|----------|
| `bm8pskStarted` | 0x01 | <Badge text="ON" variant="success" /> | | `bm8pskStarted` | 0x01 | <Badge text="ON" variant="success" /> |
| `bm8pskFW_Loaded` | 0x02 | <Badge text="ON" variant="success" /> | | `bm8pskFW_Loaded` | 0x02 | <Badge text="ON" variant="success" /> |
### test_boot_debug.py -- Incremental Stage Testing ### test_boot_debug.py -- Incremental Stage Testing
Sends debug boot modes (wValue=0x80 through 0x83) one at a time to isolate which stage of the boot sequence fails. Can test a single stage or run all sequentially. Sends debug boot modes (wValue=0x80 through 0x83) one at a time to isolate which stage of the boot sequence fails. Can test a single stage or run all sequentially.
```bash title="Run all debug stages" ```bash title="Run all debug stages"
sudo python3 tools/test_boot_debug.py sudo python3 tools/test_boot_debug.py
``` ```
```bash title="Test only stage 0x82" ```bash title="Test only stage 0x82"
sudo python3 tools/test_boot_debug.py 0x82 sudo python3 tools/test_boot_debug.py 0x82
``` ```
**Debug modes:** **Debug modes:**
| wValue | Action | Tests | | wValue | Action | Tests |
|--------|--------|-------| |--------|--------|-------|
| `0x80` | No-op: return current state | Firmware responsive? | | `0x80` | No-op: return current state | Firmware responsive? |
| `0x81` | GPIO setup + power + delays (no I2C) | Power rails working? | | `0x81` | GPIO setup + power + delays (no I2C) | Power rails working? |
| `0x82` | GPIO + I2C bus reset + BCM4500 probe | I2C communication working? | | `0x82` | GPIO + I2C bus reset + BCM4500 probe | I2C communication working? |
| `0x83` | GPIO + I2C probe + write init block 0 | Register writes accepted? | | `0x83` | GPIO + I2C probe + write init block 0 | Register writes accepted? |
Each mode returns a 3-byte response: config status, boot stage, and probe byte. The tool reports timing (ms) for each stage and checks if the device is still responsive after failures. Each mode returns a 3-byte response: config status, boot stage, and probe byte. The tool reports timing (ms) for each stage and checks if the device is still responsive after failures.
</TabItem> </TabItem>
<TabItem label="I2C Tests"> <TabItem label="I2C Tests">
## I2C Debugging Suite ## I2C Debugging Suite
Three scripts that implement a progressive isolation methodology to identify I2C bus faults. These were developed in sequence, each informed by the results of the previous one. Three scripts that implement a progressive isolation methodology to identify I2C bus faults. These were developed in sequence, each informed by the results of the previous one.
### Methodology ### Methodology
<Steps> <Steps>
1. **Broad scan** (`test_i2c_debug.py`) -- Power on the BCM4500 and probe the entire I2C bus. Does the chip respond at any address? 1. **Broad scan** (`test_i2c_debug.py`) -- Power on the BCM4500 and probe the entire I2C bus. Does the chip respond at any address?
2. **Isolation** (`test_i2c_isolate.py`) -- Determine whether the fault is in the BCM4500, the I2C bus, or the FX2 controller. Test the chip when already powered vs. after a reset. 2. **Isolation** (`test_i2c_isolate.py`) -- Determine whether the fault is in the BCM4500, the I2C bus, or the FX2 controller. Test the chip when already powered vs. after a reset.
3. **Pinpoint** (`test_i2c_pinpoint.py`) -- Identify the exact operation that corrupts communication. Compare I2C read-only, GPIO+reset, and GPIO+bus-reset+probe modes. 3. **Pinpoint** (`test_i2c_pinpoint.py`) -- Identify the exact operation that corrupts communication. Compare I2C read-only, GPIO+reset, and GPIO+bus-reset+probe modes.
</Steps> </Steps>
### test_i2c_debug.py -- Bus Discovery ### test_i2c_debug.py -- Bus Discovery
Powers on the BCM4500 via GPIO-only mode (0x81), then runs progressively detailed diagnostics. Powers on the BCM4500 via GPIO-only mode (0x81), then runs progressively detailed diagnostics.
```bash ```bash
sudo python3 tools/test_i2c_debug.py sudo python3 tools/test_i2c_debug.py
``` ```
**Test sequence:** **Test sequence:**
| Step | Action | Purpose | | Step | Action | Purpose |
|------|--------|---------| |------|--------|---------|
| 1 | Send mode 0x81 (GPIO power on) | Start BCM4500 without any I2C | | 1 | Send mode 0x81 (GPIO power on) | Start BCM4500 without any I2C |
| 2 | I2C bus scan (0xB4) immediately | Check for devices right after power-on | | 2 | I2C bus scan (0xB4) immediately | Check for devices right after power-on |
| 3 | Wait 500 ms, scan again | Maybe chip needs more time? | | 3 | Wait 500 ms, scan again | Maybe chip needs more time? |
| 4 | Raw I2C reads to candidate addresses | Try 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x11, 0x68, 0x69, 0x60, 0x61 | | 4 | Raw I2C reads to candidate addresses | Try 0x08, 0x09, 0x0A, 0x0B, 0x10, 0x11, 0x68, 0x69, 0x60, 0x61 |
| 5 | Check I2C controller state | Observe bus health | | 5 | Check I2C controller state | Observe bus health |
| 6 | Send mode 0x82 after 1s delay | Test probe with extra settling time | | 6 | Send mode 0x82 after 1s delay | Test probe with extra settling time |
**Candidate addresses** cover different BCM4500 pin-strap configurations and common demodulator/tuner addresses. **Candidate addresses** cover different BCM4500 pin-strap configurations and common demodulator/tuner addresses.
### test_i2c_isolate.py -- Fault Isolation ### test_i2c_isolate.py -- Fault Isolation
Determines whether the failure is caused by `bcm_direct_read`, re-reset timing, or the I2C bus reset (bmSTOP). Determines whether the failure is caused by `bcm_direct_read`, re-reset timing, or the I2C bus reset (bmSTOP).
```bash ```bash
sudo python3 tools/test_i2c_isolate.py sudo python3 tools/test_i2c_isolate.py
``` ```
**Test sequence:** **Test sequence:**
| Test | Action | Question | | Test | Action | Question |
|------|--------|----------| |------|--------|----------|
| **A** | Power on (0x81), wait 1s, raw read | Is BCM4500 alive from cold start? | | **A** | Power on (0x81), wait 1s, raw read | Is BCM4500 alive from cold start? |
| **B** | Run mode 0x82 (re-resets + probe) | Does `bcm_direct_read` work after reset? | | **B** | Run mode 0x82 (re-resets + probe) | Does `bcm_direct_read` work after reset? |
| **C** | Immediately raw read after 0x82 | Is I2C function itself broken? | | **C** | Immediately raw read after 0x82 | Is I2C function itself broken? |
| **D** | Raw reads at 100, 200, 500, 1000, 2000 ms | Is it a timing issue? | | **D** | Raw reads at 100, 200, 500, 1000, 2000 ms | Is it a timing issue? |
| **E** | Re-power (0x81), wait, then 0x82 | Repeatable? | | **E** | Re-power (0x81), wait, then 0x82 | Repeatable? |
### test_i2c_pinpoint.py -- Root Cause Identification ### test_i2c_pinpoint.py -- Root Cause Identification
The definitive test that identified the I2C STOP corruption bug. Compares three modes on a chip that is already proven alive. The definitive test that identified the I2C STOP corruption bug. Compares three modes on a chip that is already proven alive.
```bash ```bash
sudo python3 tools/test_i2c_pinpoint.py sudo python3 tools/test_i2c_pinpoint.py
``` ```
**Test sequence:** **Test sequence:**
<Steps> <Steps>
1. Power on BCM4500 via mode 0x81, confirm alive with raw read 1. Power on BCM4500 via mode 0x81, confirm alive with raw read
2. **Mode 0x84**: `bcm_direct_read` only (no GPIO, chip already powered) -- tests if the read function itself is broken 2. **Mode 0x84**: `bcm_direct_read` only (no GPIO, chip already powered) -- tests if the read function itself is broken
3. **Mode 0x85**: GPIO + reset + power but NO I2C bus reset (no `bmSTOP`) -- tests if re-reset breaks things 3. **Mode 0x85**: GPIO + reset + power but NO I2C bus reset (no `bmSTOP`) -- tests if re-reset breaks things
4. **Mode 0x82**: GPIO + I2C `bmSTOP` + reset + power + probe -- the mode that was failing 4. **Mode 0x82**: GPIO + I2C `bmSTOP` + reset + power + probe -- the mode that was failing
</Steps> </Steps>
**Interpretation:** **Interpretation:**
| Result Pattern | Diagnosis | | Result Pattern | Diagnosis |
|----------------|-----------| |----------------|-----------|
| 0x84 works, 0x85 works, 0x82 fails | `bmSTOP` (I2C bus reset) is the culprit | | 0x84 works, 0x85 works, 0x82 fails | `bmSTOP` (I2C bus reset) is the culprit |
| 0x84 fails | `bcm_direct_read` has a bug | | 0x84 fails | `bcm_direct_read` has a bug |
| 0x85 fails | Re-reset timing needs more delay | | 0x85 fails | Re-reset timing needs more delay |
<Aside type="note"> <Aside type="note">
This test conclusively proved that the spurious `I2CS |= bmSTOP` in the boot sequence was corrupting the FX2 I2C controller. Mode 0x84 succeeded immediately after 0x82 failed, proving the BCM4500 was alive the entire time -- only the FX2 controller was in a bad state. See [I2C STOP Corruption Bug](/i2c/stop-corruption-bug/) for the full analysis. This test conclusively proved that the spurious `I2CS |= bmSTOP` in the boot sequence was corrupting the FX2 I2C controller. Mode 0x84 succeeded immediately after 0x82 failed, proving the BCM4500 was alive the entire time -- only the FX2 controller was in a bad state. See [I2C STOP Corruption Bug](/i2c/stop-corruption-bug/) for the full analysis.
</Aside> </Aside>
</TabItem> </TabItem>
<TabItem label="Memory Extraction"> <TabItem label="Memory Extraction">
## Windows Memory Dump (wine_memdump.py) ## Windows Memory Dump (wine_memdump.py)
Extracts firmware from the Genpix Windows driver/updater by running it under Wine and dumping process memory. The Windows updater executable contains embedded firmware images that are unpacked into memory at runtime. Extracts firmware from the Genpix Windows driver/updater by running it under Wine and dumping process memory. The Windows updater executable contains embedded firmware images that are unpacked into memory at runtime.
<Aside type="note"> <Aside type="note">
This tool requires **Wine** to be installed. It reads `/proc/PID/mem` and `/proc/PID/maps`, which requires running as the same user as the Wine process or as root. This tool requires **Wine** to be installed. It reads `/proc/PID/mem` and `/proc/PID/maps`, which requires running as the same user as the Wine process or as root.
</Aside> </Aside>
```bash ```bash
sudo python3 tools/wine_memdump.py SkyWalkerUpdater.exe sudo python3 tools/wine_memdump.py SkyWalkerUpdater.exe
``` ```
```bash title="Attach to an already-running Wine process" ```bash title="Attach to an already-running Wine process"
sudo python3 tools/wine_memdump.py SkyWalkerUpdater.exe --skip-launch sudo python3 tools/wine_memdump.py SkyWalkerUpdater.exe --skip-launch
``` ```
```bash title="Custom output directory and wait time" ```bash title="Custom output directory and wait time"
sudo python3 tools/wine_memdump.py SkyWalkerUpdater.exe -o dumps/ --wait 5 sudo python3 tools/wine_memdump.py SkyWalkerUpdater.exe -o dumps/ --wait 5
``` ```
### Options ### Options
| Flag | Description | | Flag | Description |
|------|-------------| |------|-------------|
| `EXE` | Windows PE executable to run under Wine (positional, required) | | `EXE` | Windows PE executable to run under Wine (positional, required) |
| `-o, --output-dir DIR` | Output directory for dumps (default: `.`) | | `-o, --output-dir DIR` | Output directory for dumps (default: `.`) |
| `--wait SECONDS` | Seconds to wait after launch for unpacking (default: `3`) | | `--wait SECONDS` | Seconds to wait after launch for unpacking (default: `3`) |
| `--skip-launch` | Attach to an already-running Wine process | | `--skip-launch` | Attach to an already-running Wine process |
### How It Works ### How It Works
<Steps> <Steps>
1. Launches the `.exe` under Wine with `WINEDEBUG=-all` to suppress noise 1. Launches the `.exe` under Wine with `WINEDEBUG=-all` to suppress noise
2. Waits for the process to unpack (configurable delay) 2. Waits for the process to unpack (configurable delay)
3. Finds the Wine process PID by scanning `/proc` 3. Finds the Wine process PID by scanning `/proc`
4. Reads `/proc/PID/maps` to identify readable memory regions 4. Reads `/proc/PID/maps` to identify readable memory regions
5. Reads each region from `/proc/PID/mem` into a contiguous dump 5. Reads each region from `/proc/PID/mem` into a contiguous dump
6. Saves the full dump (`wine_memdump.bin`) and region map (`wine_memdump_regions.txt`) 6. Saves the full dump (`wine_memdump.bin`) and region map (`wine_memdump_regions.txt`)
7. Searches the dump for firmware signatures 7. Searches the dump for firmware signatures
</Steps> </Steps>
### Firmware Signature Search ### Firmware Signature Search
The tool searches for 7 categories of signatures: The tool searches for 7 categories of signatures:
| Search | Pattern | Purpose | | Search | Pattern | Purpose |
|--------|---------|---------| |--------|---------|---------|
| C2 EEPROM headers | `C2 C0 09 03 02` | Find embedded firmware images | | C2 EEPROM headers | `C2 C0 09 03 02` | Find embedded firmware images |
| FX2 init sequence | `78 7F E4 F6 D8 FD 75 81` | FX2 RAM clear/init code | | FX2 init sequence | `78 7F E4 F6 D8 FD 75 81` | FX2 RAM clear/init code |
| RAM clear pattern | `78 7F E4 F6 D8 FD` | Partial match variant | | RAM clear pattern | `78 7F E4 F6 D8 FD` | Partial match variant |
| C2 load records | LEN + addr `0x0000` + `LJMP` | Record chain starts | | C2 load records | LEN + addr `0x0000` + `LJMP` | Record chain starts |
| VID references | `C0 09` near `03 02` | VID/PID byte pairs | | VID references | `C0 09` near `03 02` | VID/PID byte pairs |
| Version strings | `2.13`, `SkyWalker`, `Genpix`, `8PSK`, etc. | Text markers | | Version strings | `2.13`, `SkyWalker`, `Genpix`, `8PSK`, etc. | Text markers |
| USB transfer setup | `0x40 0xA0`, `0x40 0x83`, `0x40 0x84` | WinUSB vendor request patterns | | USB transfer setup | `0x40 0xA0`, `0x40 0x83`, `0x40 0x84` | WinUSB vendor request patterns |
Each hit is reported with the dump offset, virtual address, containing memory region, and context bytes. Each hit is reported with the dump offset, virtual address, containing memory region, and context bytes.
### Output Files ### Output Files
| File | Contents | | File | Contents |
|------|----------| |------|----------|
| `wine_memdump.bin` | Full concatenated memory dump | | `wine_memdump.bin` | Full concatenated memory dump |
| `wine_memdump_regions.txt` | Region map with virtual addresses, permissions, and dump offsets | | `wine_memdump_regions.txt` | Region map with virtual addresses, permissions, and dump offsets |
</TabItem> </TabItem>
</Tabs> </Tabs>
## Diagnostic Command Reference ## Diagnostic Command Reference
The custom v3.01.0 firmware adds these diagnostic vendor commands used by the test scripts: The custom v3.01.0 firmware adds these diagnostic vendor commands used by the test scripts:
| Command | Code | Direction | Purpose | | Command | Code | Direction | Purpose |
|---------|------|-----------|---------| |---------|------|-----------|---------|
| `I2C_BUS_SCAN` | 0xB4 | IN | Probe all 128 I2C addresses, return 16-byte bitmap | | `I2C_BUS_SCAN` | 0xB4 | IN | Probe all 128 I2C addresses, return 16-byte bitmap |
| `I2C_RAW_READ` | 0xB5 | IN | Read from any I2C device (wValue=addr, wIndex=reg) | | `I2C_RAW_READ` | 0xB5 | IN | Read from any I2C device (wValue=addr, wIndex=reg) |
| `I2C_DIAG` | 0xB6 | IN | Step-by-step indirect register read with intermediate values | | `I2C_DIAG` | 0xB6 | IN | Step-by-step indirect register read with intermediate values |
| `RAW_DEMOD_READ` | 0xB1 | IN | Read any BCM4500 indirect register | | `RAW_DEMOD_READ` | 0xB1 | IN | Read any BCM4500 indirect register |
| `RAW_DEMOD_WRITE` | 0xB2 | OUT | Write any BCM4500 indirect register | | `RAW_DEMOD_WRITE` | 0xB2 | OUT | Write any BCM4500 indirect register |
These commands are only available when running the custom firmware. Stock firmware will STALL on these command codes. These commands are only available when running the custom firmware. Stock firmware will STALL on these command codes.
## See Also ## See Also
- [I2C STOP Corruption Bug](/i2c/stop-corruption-bug/) -- the bug these tools helped discover - [I2C STOP Corruption Bug](/i2c/stop-corruption-bug/) -- the bug these tools helped discover
- [Boot Sequence](/usb/boot-sequence/) -- the initialization flow being tested - [Boot Sequence](/usb/boot-sequence/) -- the initialization flow being tested
- [Custom Firmware v3.01.0](/firmware/custom-v301/) -- the firmware that enables debug modes - [Custom Firmware v3.01.0](/firmware/custom-v301/) -- the firmware that enables debug modes
- [I2C Bus Architecture](/i2c/bus-architecture/) -- I2C protocol and controller details - [I2C Bus Architecture](/i2c/bus-architecture/) -- I2C protocol and controller details
- [Firmware Loader](/tools/firmware-loader/) -- load custom firmware before running debug tools - [Firmware Loader](/tools/firmware-loader/) -- load custom firmware before running debug tools

View File

@ -1,266 +1,266 @@
--- ---
title: EEPROM Utilities title: EEPROM Utilities
description: EEPROM read, write, probe, and verification tools for the FX2 configuration EEPROM. description: EEPROM read, write, probe, and verification tools for the FX2 configuration EEPROM.
--- ---
import { Tabs, TabItem, Steps, Aside, Badge } from '@astrojs/starlight/components'; import { Tabs, TabItem, Steps, Aside, Badge } from '@astrojs/starlight/components';
Three tools manage the SkyWalker-1's I2C EEPROM (24Cxx-family at address `0x51`): `eeprom_write.py` for flashing firmware images, `eeprom_dump.py` for reading EEPROM contents, and `eeprom_probe.py` for testing I2C addressing methods. Three tools manage the SkyWalker-1's I2C EEPROM (24Cxx-family at address `0x51`): `eeprom_write.py` for flashing firmware images, `eeprom_dump.py` for reading EEPROM contents, and `eeprom_probe.py` for testing I2C addressing methods.
The EEPROM stores the Cypress FX2 boot firmware in C2 IIC format. The FX2 loads this firmware automatically on every power-up. Writing incorrect data to the EEPROM will prevent the device from enumerating on USB. The EEPROM stores the Cypress FX2 boot firmware in C2 IIC format. The FX2 loads this firmware automatically on every power-up. Writing incorrect data to the EEPROM will prevent the device from enumerating on USB.
<Aside type="danger"> <Aside type="danger">
**Writing incorrect firmware to the EEPROM can brick the device.** The SkyWalker-1 boots exclusively from this EEPROM on power-up. A corrupted image means no USB enumeration -- the device will appear dead until the EEPROM is reprogrammed using either the FX2 boot ROM's `0xA0` vendor request (if accessible) or an external I2C programmer. **Writing incorrect firmware to the EEPROM can brick the device.** The SkyWalker-1 boots exclusively from this EEPROM on power-up. A corrupted image means no USB enumeration -- the device will appear dead until the EEPROM is reprogrammed using either the FX2 boot ROM's `0xA0` vendor request (if accessible) or an external I2C programmer.
Always back up the current EEPROM contents before flashing. Always back up the current EEPROM contents before flashing.
</Aside> </Aside>
```bash ```bash
pip install pyusb pip install pyusb
``` ```
<Tabs> <Tabs>
<TabItem label="Flash (eeprom_write.py)"> <TabItem label="Flash (eeprom_write.py)">
## EEPROM Flash Tool ## EEPROM Flash Tool
`eeprom_write.py` is the full-featured EEPROM management tool with four subcommands. `eeprom_write.py` is the full-featured EEPROM management tool with four subcommands.
### Subcommands ### Subcommands
| Subcommand | Purpose | | Subcommand | Purpose |
|------------|---------| |------------|---------|
| `info` | Parse and display C2 header from a `.bin` file (offline, no device needed) | | `info` | Parse and display C2 header from a `.bin` file (offline, no device needed) |
| `backup` | Dump current EEPROM contents to a file | | `backup` | Dump current EEPROM contents to a file |
| `verify` | Compare a `.bin` file against current EEPROM contents | | `verify` | Compare a `.bin` file against current EEPROM contents |
| `flash` | Write a C2 firmware image to the EEPROM | | `flash` | Write a C2 firmware image to the EEPROM |
### info -- Inspect a C2 Image File ### info -- Inspect a C2 Image File
Parse and display the C2 header and load records from a firmware binary without connecting to the device. Parse and display the C2 header and load records from a firmware binary without connecting to the device.
```bash ```bash
python3 tools/eeprom_write.py info firmware.bin python3 tools/eeprom_write.py info firmware.bin
``` ```
``` ```
C2 Image: firmware.bin C2 Image: firmware.bin
File size: 9512 bytes File size: 9512 bytes
======================================== ========================================
Header: Header:
Format: C2 (Large EEPROM, code loads to internal RAM) Format: C2 (Large EEPROM, code loads to internal RAM)
VID: 0x09C0 (Genpix) VID: 0x09C0 (Genpix)
PID: 0x0203 (SkyWalker-1) PID: 0x0203 (SkyWalker-1)
DID: 0x0000 DID: 0x0000
Config: 0x40 (400kHz I2C) Config: 0x40 (400kHz I2C)
Load Records: Load Records:
[0] 1023 bytes -> 0x0000-0x03FE [02 18 8d 78 7f e4 f6 d8...] [0] 1023 bytes -> 0x0000-0x03FE [02 18 8d 78 7f e4 f6 d8...]
[1] 1023 bytes -> 0x03FF-0x07FD [...] [1] 1023 bytes -> 0x03FF-0x07FD [...]
... ...
[9] 115 bytes -> 0x23F7-0x2469 [...] [9] 115 bytes -> 0x23F7-0x2469 [...]
[10] END MARKER -> entry point: 0xE600 [10] END MARKER -> entry point: 0xE600
Total firmware: 9472 bytes in 10 segments Total firmware: 9472 bytes in 10 segments
Entry point: 0xE600 (LJMP target after boot) Entry point: 0xE600 (LJMP target after boot)
EEPROM footprint: 9512 bytes (0x2528) EEPROM footprint: 9512 bytes (0x2528)
``` ```
### backup -- Read EEPROM to File ### backup -- Read EEPROM to File
```bash ```bash
sudo python3 tools/eeprom_write.py backup -o my_backup.bin sudo python3 tools/eeprom_write.py backup -o my_backup.bin
``` ```
```bash title="Specify read size" ```bash title="Specify read size"
sudo python3 tools/eeprom_write.py backup -o my_backup.bin --max-size 16384 sudo python3 tools/eeprom_write.py backup -o my_backup.bin --max-size 16384
``` ```
| Flag | Description | | Flag | Description |
|------|-------------| |------|-------------|
| `-o, --output FILE` | Output file (default: `skywalker1_eeprom.bin`) | | `-o, --output FILE` | Output file (default: `skywalker1_eeprom.bin`) |
| `--max-size BYTES` | Maximum bytes to read (default: `16384`) | | `--max-size BYTES` | Maximum bytes to read (default: `16384`) |
### verify -- Compare Image Against EEPROM ### verify -- Compare Image Against EEPROM
Read the EEPROM and compare byte-by-byte against a local `.bin` file. Reports any mismatches with offset and expected vs. actual values. Read the EEPROM and compare byte-by-byte against a local `.bin` file. Reports any mismatches with offset and expected vs. actual values.
```bash ```bash
sudo python3 tools/eeprom_write.py verify firmware.bin sudo python3 tools/eeprom_write.py verify firmware.bin
``` ```
Exit code `0` = match, `1` = mismatch. Exit code `0` = match, `1` = mismatch.
### flash -- Write Image to EEPROM ### flash -- Write Image to EEPROM
The flash workflow includes built-in safety measures: image validation, VID/PID check, automatic backup, countdown timer, write verification. The flash workflow includes built-in safety measures: image validation, VID/PID check, automatic backup, countdown timer, write verification.
<Steps> <Steps>
1. **Validate** the C2 image file (header format, VID/PID match, record integrity) 1. **Validate** the C2 image file (header format, VID/PID match, record integrity)
2. **Connect** to the SkyWalker-1 and check device VID/PID against the image 2. **Connect** to the SkyWalker-1 and check device VID/PID against the image
3. **Backup** the current EEPROM contents to a timestamped file 3. **Backup** the current EEPROM contents to a timestamped file
4. **Wait** 3 seconds with a countdown (Ctrl-C to abort) 4. **Wait** 3 seconds with a countdown (Ctrl-C to abort)
5. **Write** the image in 16-byte page-aligned chunks with 10 ms write cycle delays 5. **Write** the image in 16-byte page-aligned chunks with 10 ms write cycle delays
6. **Verify** by reading back and comparing every byte 6. **Verify** by reading back and comparing every byte
</Steps> </Steps>
```bash title="Flash with all safety checks" ```bash title="Flash with all safety checks"
sudo python3 tools/eeprom_write.py flash firmware.bin sudo python3 tools/eeprom_write.py flash firmware.bin
``` ```
```bash title="Dry run (shows what would happen, writes nothing)" ```bash title="Dry run (shows what would happen, writes nothing)"
sudo python3 tools/eeprom_write.py flash firmware.bin --dry-run sudo python3 tools/eeprom_write.py flash firmware.bin --dry-run
``` ```
```bash title="Skip backup (not recommended)" ```bash title="Skip backup (not recommended)"
sudo python3 tools/eeprom_write.py flash firmware.bin --no-backup sudo python3 tools/eeprom_write.py flash firmware.bin --no-backup
``` ```
```bash title="Force flash with VID/PID mismatch" ```bash title="Force flash with VID/PID mismatch"
sudo python3 tools/eeprom_write.py flash firmware.bin --force sudo python3 tools/eeprom_write.py flash firmware.bin --force
``` ```
| Flag | Description | | Flag | Description |
|------|-------------| |------|-------------|
| `FILE` | C2 firmware image (positional, required) | | `FILE` | C2 firmware image (positional, required) |
| `--dry-run` | Validate and show plan without writing | | `--dry-run` | Validate and show plan without writing |
| `--no-backup` | Skip pre-flash EEPROM backup | | `--no-backup` | Skip pre-flash EEPROM backup |
| `--force` | Override VID/PID mismatch check | | `--force` | Override VID/PID mismatch check |
### EEPROM Write Parameters ### EEPROM Write Parameters
| Parameter | Value | | Parameter | Value |
|-----------|-------| |-----------|-------|
| I2C slave address | `0x51` (7-bit) | | I2C slave address | `0x51` (7-bit) |
| Vendor command (write) | `I2C_WRITE` (`0x83`) | | Vendor command (write) | `I2C_WRITE` (`0x83`) |
| Vendor command (read) | `I2C_READ` (`0x84`) | | Vendor command (read) | `I2C_READ` (`0x84`) |
| Page size | 16 bytes (conservative for 24Cxx) | | Page size | 16 bytes (conservative for 24Cxx) |
| Write cycle time | 10 ms per page | | Write cycle time | 10 ms per page |
| Maximum image size | 16,384 bytes (16 KB) | | Maximum image size | 16,384 bytes (16 KB) |
</TabItem> </TabItem>
<TabItem label="Dump (eeprom_dump.py)"> <TabItem label="Dump (eeprom_dump.py)">
## EEPROM Dump Tool ## EEPROM Dump Tool
`eeprom_dump.py` is a simpler read-only tool focused on extracting and analyzing EEPROM contents. `eeprom_dump.py` is a simpler read-only tool focused on extracting and analyzing EEPROM contents.
```bash ```bash
sudo python3 tools/eeprom_dump.py -o eeprom.bin sudo python3 tools/eeprom_dump.py -o eeprom.bin
``` ```
```bash title="Extract flat binary + 64K Ghidra image" ```bash title="Extract flat binary + 64K Ghidra image"
sudo python3 tools/eeprom_dump.py -o eeprom.bin --extract sudo python3 tools/eeprom_dump.py -o eeprom.bin --extract
``` ```
### Options ### Options
| Flag | Description | | Flag | Description |
|------|-------------| |------|-------------|
| `-o, --output FILE` | Output file (default: `skywalker1_eeprom.bin`) | | `-o, --output FILE` | Output file (default: `skywalker1_eeprom.bin`) |
| `--extract` | Extract firmware as flat binary + full 64K image | | `--extract` | Extract firmware as flat binary + full 64K image |
| `--max-size BYTES` | Maximum EEPROM size to read (default: `16384`) | | `--max-size BYTES` | Maximum EEPROM size to read (default: `16384`) |
### Auto-Detect End of Data ### Auto-Detect End of Data
The tool detects the end of valid data by watching for consecutive `0xFF` chunks (4 or more = end of programmed region). This avoids reading the entire EEPROM when only the first few KB contain firmware. The tool detects the end of valid data by watching for consecutive `0xFF` chunks (4 or more = end of programmed region). This avoids reading the entire EEPROM when only the first few KB contain firmware.
### Extract Mode (--extract) ### Extract Mode (--extract)
When `--extract` is specified, the tool additionally produces: When `--extract` is specified, the tool additionally produces:
- **`*_flat.bin`** -- firmware code extracted from C2 records, stored as a flat binary covering only the used address range - **`*_flat.bin`** -- firmware code extracted from C2 records, stored as a flat binary covering only the used address range
- **`*_full64k.bin`** -- full 64 KB memory image (unused regions filled with `0xFF`), suitable for loading in Ghidra at base address `0x0000` - **`*_full64k.bin`** -- full 64 KB memory image (unused regions filled with `0xFF`), suitable for loading in Ghidra at base address `0x0000`
### Output ### Output
``` ```
Genpix SkyWalker-1 EEPROM Dump Genpix SkyWalker-1 EEPROM Dump
======================================== ========================================
Found device: Bus 1 Addr 12 Found device: Bus 1 Addr 12
Reading EEPROM (max 16384 bytes)... Reading EEPROM (max 16384 bytes)...
End of data at 0x2600 (0xFF padding) End of data at 0x2600 (0xFF padding)
Read 9728 bytes total Read 9728 bytes total
Saved raw EEPROM to: eeprom.bin Saved raw EEPROM to: eeprom.bin
======================================== ========================================
EEPROM Header: EEPROM Header:
Format: C2 (Large EEPROM, code loads to internal RAM) Format: C2 (Large EEPROM, code loads to internal RAM)
VID: 0x09C0 (Genpix) VID: 0x09C0 (Genpix)
PID: 0x0203 (SkyWalker-1) PID: 0x0203 (SkyWalker-1)
DID: 0x0000 DID: 0x0000
Config: 0x40 (400kHz I2C) Config: 0x40 (400kHz I2C)
Load Records: Load Records:
[0] 1023 bytes -> 0x0000-0x03FE [02 18 8d 78 7f e4 f6 d8...] [0] 1023 bytes -> 0x0000-0x03FE [02 18 8d 78 7f e4 f6 d8...]
... ...
[10] END MARKER -> entry point: 0xE600 [10] END MARKER -> entry point: 0xE600
Total firmware: 9472 bytes in 10 records Total firmware: 9472 bytes in 10 records
Entry point: 0xE600 (LJMP target after boot) Entry point: 0xE600 (LJMP target after boot)
``` ```
</TabItem> </TabItem>
<TabItem label="Probe (eeprom_probe.py)"> <TabItem label="Probe (eeprom_probe.py)">
## EEPROM Address Probe ## EEPROM Address Probe
`eeprom_probe.py` is a diagnostic script that tests different I2C addressing methods to determine how the Genpix firmware's `I2C_READ`/`I2C_WRITE` commands interpret `wValue` and `wIndex` parameters for EEPROM access. `eeprom_probe.py` is a diagnostic script that tests different I2C addressing methods to determine how the Genpix firmware's `I2C_READ`/`I2C_WRITE` commands interpret `wValue` and `wIndex` parameters for EEPROM access.
This is a developer tool used during reverse engineering. It runs 7 different addressing approaches and checks each result against known reference bytes from the EEPROM header. This is a developer tool used during reverse engineering. It runs 7 different addressing approaches and checks each result against known reference bytes from the EEPROM header.
```bash ```bash
sudo python3 tools/eeprom_probe.py sudo python3 tools/eeprom_probe.py
``` ```
### Test Approaches ### Test Approaches
| Approach | Method | Description | | Approach | Method | Description |
|----------|--------|-------------| |----------|--------|-------------|
| 1 | `I2C_WRITE data=[addr_h, addr_l]` then `I2C_READ` | Set EEPROM offset via write data | | 1 | `I2C_WRITE data=[addr_h, addr_l]` then `I2C_READ` | Set EEPROM offset via write data |
| 2 | `wValue=addr, wIndex=slave` | Reversed parameter mapping | | 2 | `wValue=addr, wIndex=slave` | Reversed parameter mapping |
| 3 | `wValue=slave, wIndex=addr` | Standard Genpix mapping | | 3 | `wValue=slave, wIndex=addr` | Standard Genpix mapping |
| 4 | `I2C_READ wIndex=offset` | Offset in wIndex field | | 4 | `I2C_READ wIndex=offset` | Offset in wIndex field |
| 5 | `wValue=(slave<<8\|offset)` | Packed slave + offset | | 5 | `wValue=(slave<<8\|offset)` | Packed slave + offset |
| 6 | `wValue=offset (no slave)` | Offset only, no slave address | | 6 | `wValue=offset (no slave)` | Offset only, no slave address |
| 7 | Larger reads (64 bytes) | Verify sequential data across page boundaries | | 7 | Larger reads (64 bytes) | Verify sequential data across page boundaries |
### Known Reference Bytes ### Known Reference Bytes
The script compares against two known patterns: The script compares against two known patterns:
- **Offset 0x0000**: `C2 C0 09 03 02 00 00 40` (C2 header: marker, VID, PID, DID, config) - **Offset 0x0000**: `C2 C0 09 03 02 00 00 40` (C2 header: marker, VID, PID, DID, config)
- **Offset 0x0008**: `03 FF 00 00 02 18 8D 30` (first load record) - **Offset 0x0008**: `03 FF 00 00 02 18 8D 30` (first load record)
<Aside type="note"> <Aside type="note">
This tool confirmed that the Genpix firmware uses `wValue=slave_address` (0x51) and `wIndex=eeprom_offset` for the `I2C_READ` (0x84) command. Approach 4 is the correct protocol. This tool confirmed that the Genpix firmware uses `wValue=slave_address` (0x51) and `wIndex=eeprom_offset` for the `I2C_READ` (0x84) command. Approach 4 is the correct protocol.
</Aside> </Aside>
</TabItem> </TabItem>
</Tabs> </Tabs>
## Cypress C2 Boot Format ## Cypress C2 Boot Format
The EEPROM stores firmware in the Cypress C2 IIC second-stage boot format: The EEPROM stores firmware in the Cypress C2 IIC second-stage boot format:
| Field | Offset | Size | Description | | Field | Offset | Size | Description |
|-------|--------|------|-------------| |-------|--------|------|-------------|
| Marker | 0 | 1 | `0xC2` (large EEPROM, external memory) | | Marker | 0 | 1 | `0xC2` (large EEPROM, external memory) |
| VID | 1 | 2 | USB Vendor ID, little-endian (`0x09C0`) | | VID | 1 | 2 | USB Vendor ID, little-endian (`0x09C0`) |
| PID | 3 | 2 | USB Product ID, little-endian (`0x0203`) | | PID | 3 | 2 | USB Product ID, little-endian (`0x0203`) |
| DID | 5 | 2 | Device ID, little-endian | | DID | 5 | 2 | Device ID, little-endian |
| Config | 7 | 1 | Boot config (`0x40` = 400 kHz I2C) | | Config | 7 | 1 | Boot config (`0x40` = 400 kHz I2C) |
| Records | 8+ | var | Code segments: `[len_hi][len_lo][addr_hi][addr_lo][data...]` | | Records | 8+ | var | Code segments: `[len_hi][len_lo][addr_hi][addr_lo][data...]` |
| End | last | 4 | `[0x80][0x01][entry_hi][entry_lo]` (entry point = `0xE600`) | | End | last | 4 | `[0x80][0x01][entry_hi][entry_lo]` (entry point = `0xE600`) |
For a full description of the storage format, see [Firmware Storage Formats](/firmware/storage-formats/). For a full description of the storage format, see [Firmware Storage Formats](/firmware/storage-formats/).
## See Also ## See Also
- [Firmware Loader](/tools/firmware-loader/) -- RAM-based firmware loading (non-destructive) - [Firmware Loader](/tools/firmware-loader/) -- RAM-based firmware loading (non-destructive)
- [Storage Formats](/firmware/storage-formats/) -- C2 format, hexline, and FW02 chunk details - [Storage Formats](/firmware/storage-formats/) -- C2 format, hexline, and FW02 chunk details
- [Version Comparison](/firmware/version-comparison/) -- differences across firmware versions - [Version Comparison](/firmware/version-comparison/) -- differences across firmware versions
- [I2C Bus Architecture](/i2c/bus-architecture/) -- I2C protocol details - [I2C Bus Architecture](/i2c/bus-architecture/) -- I2C protocol details

View File

@ -1,255 +1,255 @@
--- ---
title: Firmware Loader title: Firmware Loader
description: RAM firmware loader and firmware dump/probe utilities for the Genpix SkyWalker-1. description: RAM firmware loader and firmware dump/probe utilities for the Genpix SkyWalker-1.
--- ---
import { Tabs, TabItem, Steps, Aside, Badge } from '@astrojs/starlight/components'; import { Tabs, TabItem, Steps, Aside, Badge } from '@astrojs/starlight/components';
Two complementary tools handle firmware on the SkyWalker-1: `fw_load.py` loads firmware into FX2 RAM for testing, and `fw_dump.py` extracts firmware and device information from a running device. Two complementary tools handle firmware on the SkyWalker-1: `fw_load.py` loads firmware into FX2 RAM for testing, and `fw_dump.py` extracts firmware and device information from a running device.
Both tools require `pyusb` and typically need root access (or appropriate udev rules) to communicate with the USB device. Both tools require `pyusb` and typically need root access (or appropriate udev rules) to communicate with the USB device.
```bash ```bash
pip install pyusb pip install pyusb
``` ```
<Aside type="danger"> <Aside type="danger">
**RAM loading is non-destructive.** The `fw_load.py` tool writes to volatile FX2 RAM only -- it never touches the EEPROM. Power-cycling the device restores the factory-programmed firmware. For permanent EEPROM programming, see [EEPROM Utilities](/tools/eeprom-utilities/). **RAM loading is non-destructive.** The `fw_load.py` tool writes to volatile FX2 RAM only -- it never touches the EEPROM. Power-cycling the device restores the factory-programmed firmware. For permanent EEPROM programming, see [EEPROM Utilities](/tools/eeprom-utilities/).
</Aside> </Aside>
<Tabs> <Tabs>
<TabItem label="Loading (fw_load.py)"> <TabItem label="Loading (fw_load.py)">
## RAM Firmware Loader ## RAM Firmware Loader
`fw_load.py` loads firmware into the Cypress FX2 internal/external RAM via the standard `0xA0` vendor request built into the FX2 silicon boot ROM. This is the primary tool for firmware development: load, test, power-cycle to revert. `fw_load.py` loads firmware into the Cypress FX2 internal/external RAM via the standard `0xA0` vendor request built into the FX2 silicon boot ROM. This is the primary tool for firmware development: load, test, power-cycle to revert.
### Subcommands ### Subcommands
| Subcommand | Purpose | | Subcommand | Purpose |
|------------|---------| |------------|---------|
| `load` | Load a firmware file into FX2 RAM | | `load` | Load a firmware file into FX2 RAM |
| `reset` | Halt and restart the FX2 CPU | | `reset` | Halt and restart the FX2 CPU |
| `read` | Read and hex-dump FX2 RAM contents | | `read` | Read and hex-dump FX2 RAM contents |
### load -- Write Firmware to RAM ### load -- Write Firmware to RAM
<Steps> <Steps>
1. **Halt the CPU** -- writes `0x01` to the CPUCS register at `0xE600` 1. **Halt the CPU** -- writes `0x01` to the CPUCS register at `0xE600`
2. **Write code segments** into RAM in 64-byte chunks via vendor request `0xA0` 2. **Write code segments** into RAM in 64-byte chunks via vendor request `0xA0`
3. **Start the CPU** -- writes `0x00` to CPUCS, triggering USB re-enumeration 3. **Start the CPU** -- writes `0x00` to CPUCS, triggering USB re-enumeration
</Steps> </Steps>
**Supported file formats:** **Supported file formats:**
| Extension | Format | Load Address | | Extension | Format | Load Address |
|-----------|--------|-------------| |-----------|--------|-------------|
| `.ihx`, `.hex` | Intel HEX | Addresses embedded in file | | `.ihx`, `.hex` | Intel HEX | Addresses embedded in file |
| `.bix`, `.bin` | Raw binary | `0x0000` (start of internal RAM) | | `.bix`, `.bin` | Raw binary | `0x0000` (start of internal RAM) |
**Options:** **Options:**
| Flag | Description | | Flag | Description |
|------|-------------| |------|-------------|
| `FILE` | Firmware file path (positional, required) | | `FILE` | Firmware file path (positional, required) |
| `--no-reset` | Load segments without halting/starting the CPU | | `--no-reset` | Load segments without halting/starting the CPU |
| `--wait SECONDS` | Wait for USB re-enumeration after load | | `--wait SECONDS` | Wait for USB re-enumeration after load |
| `-v, --verbose` | Show per-chunk transfer progress | | `-v, --verbose` | Show per-chunk transfer progress |
| `--force` | Allow loading to devices with unknown VID/PID | | `--force` | Allow loading to devices with unknown VID/PID |
**Examples:** **Examples:**
```bash title="Load custom firmware and wait for re-enumeration" ```bash title="Load custom firmware and wait for re-enumeration"
sudo python3 tools/fw_load.py load firmware/build/skywalker1.ihx --wait 3 sudo python3 tools/fw_load.py load firmware/build/skywalker1.ihx --wait 3
``` ```
```bash title="Load raw binary with verbose output" ```bash title="Load raw binary with verbose output"
sudo python3 tools/fw_load.py load firmware.bix -v --wait 5 sudo python3 tools/fw_load.py load firmware.bix -v --wait 5
``` ```
```bash title="Load without CPU reset (write segments only)" ```bash title="Load without CPU reset (write segments only)"
sudo python3 tools/fw_load.py load firmware.ihx --no-reset sudo python3 tools/fw_load.py load firmware.ihx --no-reset
``` ```
**Typical output:** **Typical output:**
``` ```
SkyWalker-1 RAM Firmware Loader SkyWalker-1 RAM Firmware Loader
======================================== ========================================
Firmware: firmware/build/skywalker1.ihx Firmware: firmware/build/skywalker1.ihx
Segments: 3 Segments: 3
Total size: 3072 bytes Total size: 3072 bytes
Address: 0x0000 - 0x0BFF Address: 0x0000 - 0x0BFF
Found SkyWalker-1: Bus 1 Addr 12 (VID 0x09C0 PID 0x0203) Found SkyWalker-1: Bus 1 Addr 12 (VID 0x09C0 PID 0x0203)
[1/3] Halting CPU (CPUCS = 0x01)... [1/3] Halting CPU (CPUCS = 0x01)...
CPU halted CPU halted
[2/3] Loading 3 segment(s) into RAM... [2/3] Loading 3 segment(s) into RAM...
0x0000-0x03FF (1024 bytes) 0x0000-0x03FF (1024 bytes)
0x0400-0x07FF (1024 bytes) 0x0400-0x07FF (1024 bytes)
0x0800-0x0BFF (1024 bytes) 0x0800-0x0BFF (1024 bytes)
3072 bytes loaded 3072 bytes loaded
[3/3] Starting CPU (CPUCS = 0x00)... [3/3] Starting CPU (CPUCS = 0x00)...
CPU released CPU released
Firmware is running. The device will re-enumerate Firmware is running. The device will re-enumerate
with new USB descriptors if the firmware does so. with new USB descriptors if the firmware does so.
``` ```
### reset -- Restart the FX2 CPU ### reset -- Restart the FX2 CPU
Halts and restarts the CPU without loading new code. Useful for triggering USB re-enumeration when the device is in a bad state. Halts and restarts the CPU without loading new code. Useful for triggering USB re-enumeration when the device is in a bad state.
```bash ```bash
sudo python3 tools/fw_load.py reset --wait 3 sudo python3 tools/fw_load.py reset --wait 3
``` ```
| Flag | Description | | Flag | Description |
|------|-------------| |------|-------------|
| `--wait SECONDS` | Wait for re-enumeration after reset | | `--wait SECONDS` | Wait for re-enumeration after reset |
| `--force` | Allow reset on unknown VID/PID | | `--force` | Allow reset on unknown VID/PID |
### read -- Hex-Dump FX2 RAM ### read -- Hex-Dump FX2 RAM
Read memory contents from a running FX2. Useful for verifying loaded firmware or inspecting register state. Read memory contents from a running FX2. Useful for verifying loaded firmware or inspecting register state.
```bash title="Read first 256 bytes of internal RAM" ```bash title="Read first 256 bytes of internal RAM"
sudo python3 tools/fw_load.py read --addr 0x0000 --len 256 sudo python3 tools/fw_load.py read --addr 0x0000 --len 256
``` ```
```bash title="Check CPUCS register" ```bash title="Check CPUCS register"
sudo python3 tools/fw_load.py read --addr 0xe600 --len 1 sudo python3 tools/fw_load.py read --addr 0xe600 --len 1
``` ```
```bash title="Dump to file" ```bash title="Dump to file"
sudo python3 tools/fw_load.py read --addr 0x0000 --len 8192 -o ram_dump.bin sudo python3 tools/fw_load.py read --addr 0x0000 --len 8192 -o ram_dump.bin
``` ```
| Flag | Description | | Flag | Description |
|------|-------------| |------|-------------|
| `--addr ADDR` | Start address in hex (default: `0x0000`) | | `--addr ADDR` | Start address in hex (default: `0x0000`) |
| `--len LENGTH` | Bytes to read (default: `256`) | | `--len LENGTH` | Bytes to read (default: `256`) |
| `-o, --output FILE` | Save raw bytes to file | | `-o, --output FILE` | Save raw bytes to file |
| `--force` | Allow read on unknown VID/PID | | `--force` | Allow read on unknown VID/PID |
### Device Detection ### Device Detection
The loader searches for devices in this order: The loader searches for devices in this order:
1. **SkyWalker-1** -- VID `0x09C0`, PID `0x0203` 1. **SkyWalker-1** -- VID `0x09C0`, PID `0x0203`
2. **Bare Cypress FX2** -- VID `0x04B4`, PID `0x8613` (unprogrammed/blank EEPROM) 2. **Bare Cypress FX2** -- VID `0x04B4`, PID `0x8613` (unprogrammed/blank EEPROM)
Use `--force` to override VID/PID checks for devices with non-standard descriptors. Use `--force` to override VID/PID checks for devices with non-standard descriptors.
<Aside type="tip"> <Aside type="tip">
**Recovery procedure:** If the device is completely hung (not responding to vendor commands), you can still recover it using `fw_load.py`. The FX2's `0xA0` vendor request is handled by the boot ROM in silicon, not by user firmware. Even a hung 8051 CPU can be halted and reprogrammed via this mechanism. **Recovery procedure:** If the device is completely hung (not responding to vendor commands), you can still recover it using `fw_load.py`. The FX2's `0xA0` vendor request is handled by the boot ROM in silicon, not by user firmware. Even a hung 8051 CPU can be halted and reprogrammed via this mechanism.
</Aside> </Aside>
</TabItem> </TabItem>
<TabItem label="Dumping (fw_dump.py)"> <TabItem label="Dumping (fw_dump.py)">
## Firmware Probe and Dump Tool ## Firmware Probe and Dump Tool
`fw_dump.py` queries device information, dumps FX2 RAM contents, and scans for undocumented vendor commands. `fw_dump.py` queries device information, dumps FX2 RAM contents, and scans for undocumented vendor commands.
### Options ### Options
| Flag | Description | | Flag | Description |
|------|-------------| |------|-------------|
| `--info` | Query and display device information | | `--info` | Query and display device information |
| `--dump FILE` | Dump FX2 RAM to a binary file | | `--dump FILE` | Dump FX2 RAM to a binary file |
| `--scan` | Brute-force scan all vendor commands (0x00--0xFF) | | `--scan` | Brute-force scan all vendor commands (0x00--0xFF) |
| `--start ADDR` | RAM dump start address (default: `0x0000`) | | `--start ADDR` | RAM dump start address (default: `0x0000`) |
| `--size SIZE` | RAM dump size in bytes (default: `0x2000` = 8 KB) | | `--size SIZE` | RAM dump size in bytes (default: `0x2000` = 8 KB) |
| `--external` | Attempt to dump external RAM (64 KB) | | `--external` | Attempt to dump external RAM (64 KB) |
Running with no flags defaults to `--info --scan`. Running with no flags defaults to `--info --scan`.
### Device Info (--info) ### Device Info (--info)
Queries all known Genpix vendor commands and displays firmware version, build date, USB speed, serial number, and the 8PSK configuration status byte with decoded flags. Queries all known Genpix vendor commands and displays firmware version, build date, USB speed, serial number, and the 8PSK configuration status byte with decoded flags.
```bash ```bash
sudo python3 tools/fw_dump.py --info sudo python3 tools/fw_dump.py --info
``` ```
``` ```
=== Genpix SkyWalker-1 Device Info === === Genpix SkyWalker-1 Device Info ===
FW Version: 2.06.4 (0x020604) FW Version: 2.06.4 (0x020604)
FW Build: 2007-07-13 FW Build: 2007-07-13
BCD Version: 0206 BCD Version: 0206
Vendor: Genpix Vendor: Genpix
Product: SkyWalker-1 Product: SkyWalker-1
USB Speed: High (480Mbps) USB Speed: High (480Mbps)
Serial: 00000000 Serial: 00000000
Config: 0x03 Config: 0x03
[ ON] 8PSK Started [ ON] 8PSK Started
[ ON] BCM4500 FW Loaded [ ON] BCM4500 FW Loaded
[off] Intersil LNB On [off] Intersil LNB On
[off] DVB Mode [off] DVB Mode
[off] 22kHz Tone [off] 22kHz Tone
[off] 18V Selected [off] 18V Selected
[off] DC Tuned [off] DC Tuned
[off] Armed (streaming) [off] Armed (streaming)
``` ```
### Vendor Command Scan (--scan) ### Vendor Command Scan (--scan)
Sends vendor IN requests to every command index from `0x00` to `0xFF` and reports which ones return data. Commands already documented in the reference are labeled `[KNOWN]`; unexpected responses are flagged `[NEW!]`. Sends vendor IN requests to every command index from `0x00` to `0xFF` and reports which ones return data. Commands already documented in the reference are labeled `[KNOWN]`; unexpected responses are flagged `[NEW!]`.
```bash ```bash
sudo python3 tools/fw_dump.py --scan sudo python3 tools/fw_dump.py --scan
``` ```
### RAM Dump (--dump) ### RAM Dump (--dump)
Reads FX2 internal RAM (8 KB at `0x0000`--`0x1FFF`) or external RAM (up to 64 KB with `--external`) via the standard `0xA0` vendor request. Reads FX2 internal RAM (8 KB at `0x0000`--`0x1FFF`) or external RAM (up to 64 KB with `--external`) via the standard `0xA0` vendor request.
```bash title="Dump internal RAM" ```bash title="Dump internal RAM"
sudo python3 tools/fw_dump.py --dump internal_ram.bin sudo python3 tools/fw_dump.py --dump internal_ram.bin
``` ```
```bash title="Dump external RAM (64 KB)" ```bash title="Dump external RAM (64 KB)"
sudo python3 tools/fw_dump.py --dump external_ram.bin --external sudo python3 tools/fw_dump.py --dump external_ram.bin --external
``` ```
```bash title="Dump specific range" ```bash title="Dump specific range"
sudo python3 tools/fw_dump.py --dump region.bin --start 0x1000 --size 0x800 sudo python3 tools/fw_dump.py --dump region.bin --start 0x1000 --size 0x800
``` ```
The tool performs a quick analysis of the dump, reporting non-`0xFF` byte count and checking for the standard FX2 reset vector (`LJMP` at address `0x0000`). The tool performs a quick analysis of the dump, reporting non-`0xFF` byte count and checking for the standard FX2 reset vector (`LJMP` at address `0x0000`).
<Aside type="note"> <Aside type="note">
RAM readback may fail if the running firmware has disabled or overridden the `0xA0` vendor request. Stock Genpix firmware supports `0xA0` readback; some custom configurations may not. If you see consecutive read failures, the device firmware may need to be reloaded first. RAM readback may fail if the running firmware has disabled or overridden the `0xA0` vendor request. Stock Genpix firmware supports `0xA0` readback; some custom configurations may not. If you see consecutive read failures, the device firmware may need to be reloaded first.
</Aside> </Aside>
</TabItem> </TabItem>
</Tabs> </Tabs>
## Kernel Driver Conflict ## Kernel Driver Conflict
The Linux `dvb_usb_gp8psk` module auto-loads when the SkyWalker-1 enumerates on USB. It will race with these tools for device access. The Linux `dvb_usb_gp8psk` module auto-loads when the SkyWalker-1 enumerates on USB. It will race with these tools for device access.
**Before using any tool**, either blacklist the module or unload it: **Before using any tool**, either blacklist the module or unload it:
```bash title="Unload for current session" ```bash title="Unload for current session"
sudo modprobe -r dvb_usb_gp8psk gp8psk_fe sudo modprobe -r dvb_usb_gp8psk gp8psk_fe
``` ```
```bash title="Permanent blacklist" ```bash title="Permanent blacklist"
echo -e "blacklist dvb_usb_gp8psk\nblacklist gp8psk_fe" | \ echo -e "blacklist dvb_usb_gp8psk\nblacklist gp8psk_fe" | \
sudo tee /etc/modprobe.d/blacklist-gp8psk.conf sudo tee /etc/modprobe.d/blacklist-gp8psk.conf
``` ```
## See Also ## See Also
- [EEPROM Utilities](/tools/eeprom-utilities/) -- for permanent firmware flashing - [EEPROM Utilities](/tools/eeprom-utilities/) -- for permanent firmware flashing
- [Boot Sequence](/usb/boot-sequence/) -- what happens after firmware loads - [Boot Sequence](/usb/boot-sequence/) -- what happens after firmware loads
- [Custom Firmware v3.01.0](/firmware/custom-v301/) -- the open-source replacement firmware - [Custom Firmware v3.01.0](/firmware/custom-v301/) -- the open-source replacement firmware
- [Vendor Commands](/usb/vendor-commands/) -- command reference used by these tools - [Vendor Commands](/usb/vendor-commands/) -- command reference used by these tools

View File

@ -1,131 +1,131 @@
--- ---
title: Hydrogen 21 cm Radiometer title: Hydrogen 21 cm Radiometer
description: Detect neutral hydrogen emission at 1420.405 MHz using the SkyWalker-1 as an L-band radiometer. description: Detect neutral hydrogen emission at 1420.405 MHz using the SkyWalker-1 as an L-band radiometer.
--- ---
import { Aside, Card, CardGrid, Steps, Tabs, TabItem } from '@astrojs/starlight/components'; import { Aside, Card, CardGrid, Steps, Tabs, TabItem } from '@astrojs/starlight/components';
The `h21cm.py` tool turns the SkyWalker-1 into a hydrogen line radiometer. Neutral hydrogen The `h21cm.py` tool turns the SkyWalker-1 into a hydrogen line radiometer. Neutral hydrogen
atoms emit radiation at **1420.405 MHz** when the electron's spin flips relative to the proton — atoms emit radiation at **1420.405 MHz** when the electron's spin flips relative to the proton —
the most fundamental spectral line in radio astronomy, and it falls directly in the IF range. the most fundamental spectral line in radio astronomy, and it falls directly in the IF range.
## Antenna Setup ## Antenna Setup
The SkyWalker-1 normally receives satellite TV through an LNB (Low Noise Block downconverter) mounted The SkyWalker-1 normally receives satellite TV through an LNB (Low Noise Block downconverter) mounted
at the focal point of a dish. For hydrogen line work, the LNB must be **removed or bypassed entirely** — at the focal point of a dish. For hydrogen line work, the LNB must be **removed or bypassed entirely** —
it would block the signal. An LNB's waveguide feed is dimensioned for Ku-band wavelengths (~2.5 cm) it would block the signal. An LNB's waveguide feed is dimensioned for Ku-band wavelengths (~2.5 cm)
and its internal filters reject everything outside the 10.7-12.75 GHz range. At 1420 MHz (wavelength and its internal filters reject everything outside the 10.7-12.75 GHz range. At 1420 MHz (wavelength
~21 cm), nothing gets through. ~21 cm), nothing gets through.
Instead, connect an L-band antenna directly to the SkyWalker-1's F-connector with coaxial cable. Instead, connect an L-band antenna directly to the SkyWalker-1's F-connector with coaxial cable.
The tool disables LNB power automatically, so there's no voltage on the cable. The tool disables LNB power automatically, so there's no voltage on the cable.
### Antenna Options ### Antenna Options
<CardGrid> <CardGrid>
<Card title="Horn Antenna" icon="rocket"> <Card title="Horn Antenna" icon="rocket">
The classic radio astronomy choice. A tin-can "cantenna" or sheet-metal pyramidal horn provides The classic radio astronomy choice. A tin-can "cantenna" or sheet-metal pyramidal horn provides
10-15 dBi gain with predictable, calculable performance. Easy to build from hardware store materials. 10-15 dBi gain with predictable, calculable performance. Easy to build from hardware store materials.
A circular waveguide horn from a ~15 cm diameter can works well at 1420 MHz. A circular waveguide horn from a ~15 cm diameter can works well at 1420 MHz.
</Card> </Card>
<Card title="Dish + L-Band Feed" icon="star"> <Card title="Dish + L-Band Feed" icon="star">
Reuse your satellite dish — replace the LNB with a 1420 MHz feed (dipole + reflector, or a small Reuse your satellite dish — replace the LNB with a 1420 MHz feed (dipole + reflector, or a small
horn at the focal point). The dish surface accuracy matters less at 21 cm wavelength than at Ku-band, horn at the focal point). The dish surface accuracy matters less at 21 cm wavelength than at Ku-band,
so even mesh dishes work fine. This gives the highest gain of any option here. so even mesh dishes work fine. This gives the highest gain of any option here.
</Card> </Card>
<Card title="Helical Antenna" icon="setting"> <Card title="Helical Antenna" icon="setting">
A helical antenna is circularly polarized and offers good gain in a compact package. Hydrogen emission A helical antenna is circularly polarized and offers good gain in a compact package. Hydrogen emission
is unpolarized, so a circularly-polarized antenna captures half the power (~3 dB penalty vs linear), is unpolarized, so a circularly-polarized antenna captures half the power (~3 dB penalty vs linear),
but helix construction is forgiving and well-documented for L-band. but helix construction is forgiving and well-documented for L-band.
</Card> </Card>
<Card title="Patch Antenna" icon="open-book"> <Card title="Patch Antenna" icon="open-book">
Commercial L-band patch antennas (GPS antennas at 1575 MHz are close) are compact and cheap. Lower Commercial L-band patch antennas (GPS antennas at 1575 MHz are close) are compact and cheap. Lower
gain than the other options (~5-7 dBi), and narrow bandwidth may not cover the full hydrogen emission gain than the other options (~5-7 dBi), and narrow bandwidth may not cover the full hydrogen emission
profile. Fine for a first detection attempt. profile. Fine for a first detection attempt.
</Card> </Card>
</CardGrid> </CardGrid>
<Aside type="note" title="Impedance mismatch"> <Aside type="note" title="Impedance mismatch">
The SkyWalker-1's F-connector is 75&Omega;. Most L-band antennas and amateur radio feedlines are 50&Omega;. The SkyWalker-1's F-connector is 75&Omega;. Most L-band antennas and amateur radio feedlines are 50&Omega;.
The resulting 1.5:1 VSWR costs about **0.2 dB** of mismatch loss — negligible for AGC power detection. The resulting 1.5:1 VSWR costs about **0.2 dB** of mismatch loss — negligible for AGC power detection.
No matching network is needed. Use an SMA-to-F adapter if your antenna has an SMA connector. No matching network is needed. Use an SMA-to-F adapter if your antenna has an SMA connector.
</Aside> </Aside>
### Cable and Connectors ### Cable and Connectors
Run 75&Omega; coax (RG-6 is standard satellite TV cable) from the antenna to the SkyWalker-1. At 1420 MHz, Run 75&Omega; coax (RG-6 is standard satellite TV cable) from the antenna to the SkyWalker-1. At 1420 MHz,
cable loss matters more than impedance mismatch — keep runs under 10 meters if possible. RG-6 loses cable loss matters more than impedance mismatch — keep runs under 10 meters if possible. RG-6 loses
roughly **0.2 dB per meter** at 1.4 GHz (about 6 dB per 100 feet), so a 10m run costs ~2 dB. roughly **0.2 dB per meter** at 1.4 GHz (about 6 dB per 100 feet), so a 10m run costs ~2 dB.
Shorter is better. Shorter is better.
If your antenna uses 50&Omega; connectors (SMA, N-type), a simple adapter to F-type is fine. The 0.2 dB If your antenna uses 50&Omega; connectors (SMA, N-type), a simple adapter to F-type is fine. The 0.2 dB
impedance mismatch is far less than a meter of extra cable. impedance mismatch is far less than a meter of extra cable.
## Quick Start ## Quick Start
```bash ```bash
# Single sweep, 8x averaging for best sensitivity # Single sweep, 8x averaging for best sensitivity
python tools/h21cm.py --averages 8 python tools/h21cm.py --averages 8
# One-hour drift scan with CSV output # One-hour drift scan with CSV output
python tools/h21cm.py --drift --duration 3600 --averages 4 --output h21cm-data.csv python tools/h21cm.py --drift --duration 3600 --averages 4 --output h21cm-data.csv
``` ```
## How It Works ## How It Works
<Steps> <Steps>
1. **LNB power is disabled** — direct input mode, no frequency conversion 1. **LNB power is disabled** — direct input mode, no frequency conversion
2. **Sweeps 1418-1422 MHz** (configurable) at 0.5 MHz steps 2. **Sweeps 1418-1422 MHz** (configurable) at 0.5 MHz steps
3. **Measures AGC power** at each step — the BCM4500 responds to any RF energy 3. **Measures AGC power** at each step — the BCM4500 responds to any RF energy
4. **Estimates baseline** from the band edges (where no hydrogen is expected) 4. **Estimates baseline** from the band edges (where no hydrogen is expected)
5. **Calculates excess power** above baseline — the hydrogen emission 5. **Calculates excess power** above baseline — the hydrogen emission
6. **Computes Doppler velocity** for each frequency bin 6. **Computes Doppler velocity** for each frequency bin
</Steps> </Steps>
The velocity axis maps frequency to radial velocity via: The velocity axis maps frequency to radial velocity via:
**v = c × (1420.405 f_observed) / 1420.405** **v = c × (1420.405 f_observed) / 1420.405**
Positive velocity = hydrogen moving away (lower frequency). The ~200 km/s spread Positive velocity = hydrogen moving away (lower frequency). The ~200 km/s spread
in a typical observation maps the rotation curve of the Milky Way. in a typical observation maps the rotation curve of the Milky Way.
## Options ## Options
| Flag | Default | Description | | Flag | Default | Description |
|---|---|---| |---|---|---|
| `--center` | 1420.405 | Center frequency in MHz | | `--center` | 1420.405 | Center frequency in MHz |
| `--span` | 4.0 | Frequency span in MHz | | `--span` | 4.0 | Frequency span in MHz |
| `--step` | 0.5 | Frequency step in MHz | | `--step` | 0.5 | Frequency step in MHz |
| `--dwell` | 50 | Integration time per step in ms | | `--dwell` | 50 | Integration time per step in ms |
| `--averages` | 1 | Number of sweeps to average (4-16 recommended) | | `--averages` | 1 | Number of sweeps to average (4-16 recommended) |
| `--output` | — | CSV output file | | `--output` | — | CSV output file |
| `--control` | — | Include control band comparison | | `--control` | — | Include control band comparison |
| `--drift` | — | Enable drift scan mode | | `--drift` | — | Enable drift scan mode |
| `--duration` | 3600 | Drift scan duration in seconds | | `--duration` | 3600 | Drift scan duration in seconds |
| `--interval` | 60 | Seconds between drift scans | | `--interval` | 60 | Seconds between drift scans |
| `--motor-step` | 0 | Motor steps between scans (declination scanning) | | `--motor-step` | 0 | Motor steps between scans (declination scanning) |
## Sensitivity Notes ## Sensitivity Notes
<Aside type="tip" title="Improving SNR"> <Aside type="tip" title="Improving SNR">
The hydrogen line is weak. The BCM4500's ~346 kHz resolution bandwidth is actually The hydrogen line is weak. The BCM4500's ~346 kHz resolution bandwidth is actually
helpful here — it's wide enough to capture the broad galactic emission without helpful here — it's wide enough to capture the broad galactic emission without
excessive noise. Use `--averages 8` or higher and `--dwell 100` for best results. excessive noise. Use `--averages 8` or higher and `--dwell 100` for best results.
Each doubling of averages improves SNR by ~3 dB. Each doubling of averages improves SNR by ~3 dB.
</Aside> </Aside>
The `--control` flag sweeps an adjacent band (1430-1434 MHz) where no hydrogen emission The `--control` flag sweeps an adjacent band (1430-1434 MHz) where no hydrogen emission
is expected. Comparing the two bands confirms that any detected bump is real signal, is expected. Comparing the two bands confirms that any detected bump is real signal,
not system noise variation. not system noise variation.
## CSV Output Format ## CSV Output Format
| Column | Description | | Column | Description |
|---|---| |---|---|
| `timestamp` | ISO 8601 UTC timestamp | | `timestamp` | ISO 8601 UTC timestamp |
| `scan_num` | Scan number (drift mode only) | | `scan_num` | Scan number (drift mode only) |
| `freq_mhz` | Frequency in MHz | | `freq_mhz` | Frequency in MHz |
| `power_db` | Raw power in dB (relative) | | `power_db` | Raw power in dB (relative) |
| `excess_db` | Power above baseline | | `excess_db` | Power above baseline |
| `velocity_km_s` | Doppler velocity in km/s | | `velocity_km_s` | Doppler velocity in km/s |
| `baseline_db` | Estimated noise floor | | `baseline_db` | Estimated noise floor |

View File

@ -1,112 +1,112 @@
--- ---
title: MCP Server title: MCP Server
description: Model Context Protocol server that exposes the SkyWalker-1 hardware API to LLMs for autonomous RF exploration. description: Model Context Protocol server that exposes the SkyWalker-1 hardware API to LLMs for autonomous RF exploration.
--- ---
import { Aside, Steps } from '@astrojs/starlight/components'; import { Aside, Steps } from '@astrojs/starlight/components';
The `skywalker-mcp` package wraps the entire SkyWalker-1 Python API as an MCP (Model Context Protocol) The `skywalker-mcp` package wraps the entire SkyWalker-1 Python API as an MCP (Model Context Protocol)
server, making every hardware function accessible to LLMs. This enables natural-language signal analysis, server, making every hardware function accessible to LLMs. This enables natural-language signal analysis,
autonomous RF exploration, and scheduled observation campaigns. autonomous RF exploration, and scheduled observation campaigns.
## Installation ## Installation
```bash ```bash
cd mcp/skywalker-mcp cd mcp/skywalker-mcp
uv sync uv sync
``` ```
## Running ## Running
```bash ```bash
# Local development # Local development
uv run --directory mcp/skywalker-mcp skywalker-mcp uv run --directory mcp/skywalker-mcp skywalker-mcp
# Add to Claude Code # Add to Claude Code
claude mcp add skywalker-mcp -- uv run --directory mcp/skywalker-mcp skywalker-mcp claude mcp add skywalker-mcp -- uv run --directory mcp/skywalker-mcp skywalker-mcp
``` ```
## Tools (20) ## Tools (20)
### Device Status ### Device Status
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `get_device_status` | Firmware version, config bits, USB speed, serial, last error | | `get_device_status` | Firmware version, config bits, USB speed, serial, last error |
| `get_signal_quality` | SNR, AGC, power, lock status | | `get_signal_quality` | SNR, AGC, power, lock status |
| `get_stream_diagnostics` | Poll count, overflows, sync loss | | `get_stream_diagnostics` | Poll count, overflows, sync loss |
### Spectrum & Tuning ### Spectrum & Tuning
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `sweep_spectrum` | Full-band power measurement with peak detection | | `sweep_spectrum` | Full-band power measurement with peak detection |
| `tune_frequency` | Tune to specific freq/modulation/FEC, read signal | | `tune_frequency` | Tune to specific freq/modulation/FEC, read signal |
| `run_blind_scan` | Symbol rate sweep at single frequency | | `run_blind_scan` | Symbol rate sweep at single frequency |
### Survey & Catalog ### Survey & Catalog
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `run_carrier_survey` | Six-stage pipeline: sweep → peaks → blind → TS → catalog | | `run_carrier_survey` | Six-stage pipeline: sweep → peaks → blind → TS → catalog |
| `compare_surveys` | Diff two saved catalogs for changes | | `compare_surveys` | Diff two saved catalogs for changes |
| `list_surveys` | List saved survey files with metadata | | `list_surveys` | List saved survey files with metadata |
### Dish Motor ### Dish Motor
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `move_dish` | Halt, east, west, goto slot, USALS GotoX (continuous drive requires explicit opt-in) | | `move_dish` | Halt, east, west, goto slot, USALS GotoX (continuous drive requires explicit opt-in) |
| `jog_dish` | Small steps (1-30) + signal quality readback | | `jog_dish` | Small steps (1-30) + signal quality readback |
| `store_position` | Save current position to memory slot | | `store_position` | Save current position to memory slot |
### LNB & I2C ### LNB & I2C
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `set_lnb_config` | Voltage (13V/18V), 22 kHz tone, power off | | `set_lnb_config` | Voltage (13V/18V), 22 kHz tone, power off |
| `scan_i2c_bus` | Enumerate all I2C devices | | `scan_i2c_bus` | Enumerate all I2C devices |
| `read_i2c_register` | Read single byte from I2C address | | `read_i2c_register` | Read single byte from I2C address |
### Transport Stream & Identification ### Transport Stream & Identification
| Tool | Description | | Tool | Description |
|---|---| |---|---|
| `capture_transport_stream` | Capture + parse PAT/PMT/SDT for service names | | `capture_transport_stream` | Capture + parse PAT/PMT/SDT for service names |
| `identify_frequency` | Look up frequency against allocation tables | | `identify_frequency` | Look up frequency against allocation tables |
## Resources ## Resources
| URI | Description | | URI | Description |
|---|---| |---|---|
| `skywalker://status` | Live device state (firmware, config, signal) | | `skywalker://status` | Live device state (firmware, config, signal) |
| `skywalker://catalog/latest` | Most recent survey catalog as JSON | | `skywalker://catalog/latest` | Most recent survey catalog as JSON |
| `skywalker://allocations/lband` | L-band frequency allocation table | | `skywalker://allocations/lband` | L-band frequency allocation table |
| `skywalker://modulations` | Supported modulations and FEC rates | | `skywalker://modulations` | Supported modulations and FEC rates |
## Prompts ## Prompts
| Prompt | Description | | Prompt | Description |
|---|---| |---|---|
| `explore_rf_environment` | Strategy for autonomous RF discovery | | `explore_rf_environment` | Strategy for autonomous RF discovery |
| `hydrogen_line_observation` | Guided 21 cm observation procedure | | `hydrogen_line_observation` | Guided 21 cm observation procedure |
## Architecture ## Architecture
<Aside type="note" title="Thread safety"> <Aside type="note" title="Thread safety">
The BCM4500 demodulator cannot handle overlapping USB control transfers. The MCP server The BCM4500 demodulator cannot handle overlapping USB control transfers. The MCP server
uses the same `DeviceBridge` pattern as the TUI — a `threading.RLock` serializes all uses the same `DeviceBridge` pattern as the TUI — a `threading.RLock` serializes all
hardware access. Async MCP handlers use `asyncio.to_thread()` to avoid blocking the hardware access. Async MCP handlers use `asyncio.to_thread()` to avoid blocking the
event loop during USB I/O. event loop during USB I/O.
</Aside> </Aside>
The server uses FastMCP's lifespan pattern: the USB device opens on server startup and The server uses FastMCP's lifespan pattern: the USB device opens on server startup and
closes on shutdown. All tools receive the device bridge through the lifespan context. closes on shutdown. All tools receive the device bridge through the lifespan context.
## Testing ## Testing
```bash ```bash
# Verify the server starts and can talk to hardware # Verify the server starts and can talk to hardware
claude -p "What firmware version is loaded?" \ claude -p "What firmware version is loaded?" \
--mcp-config .mcp.json \ --mcp-config .mcp.json \
--allowedTools "mcp__skywalker-mcp__*" --allowedTools "mcp__skywalker-mcp__*"
# Run a spectrum sweep via natural language # Run a spectrum sweep via natural language
claude -p "Sweep the full IF band and tell me what you find" \ claude -p "Sweep the full IF band and tell me what you find" \
--mcp-config .mcp.json \ --mcp-config .mcp.json \
--allowedTools "mcp__skywalker-mcp__*" --allowedTools "mcp__skywalker-mcp__*"
``` ```

View File

@ -1,107 +1,107 @@
--- ---
title: Motor Control title: Motor Control
description: DiSEqC 1.2 positioner motor control with USALS GotoX, stored positions, and live signal feedback for dish alignment. description: DiSEqC 1.2 positioner motor control with USALS GotoX, stored positions, and live signal feedback for dish alignment.
--- ---
import { Tabs, TabItem, Steps, Aside, Badge } from '@astrojs/starlight/components'; import { Tabs, TabItem, Steps, Aside, Badge } from '@astrojs/starlight/components';
Command-line tool for driving a DiSEqC 1.2 positioner motor through the SkyWalker-1. Supports continuous jog, stored positions, USALS GotoX calculations, and an interactive keyboard-driven mode with live signal feedback for hands-free dish alignment. Command-line tool for driving a DiSEqC 1.2 positioner motor through the SkyWalker-1. Supports continuous jog, stored positions, USALS GotoX calculations, and an interactive keyboard-driven mode with live signal feedback for hands-free dish alignment.
<Badge text="Requires custom firmware v3.03.0+" variant="caution" /> <Badge text="Requires custom firmware v3.03.0+" variant="caution" />
## Usage ## Usage
```bash title="Interactive motor jog with live signal" ```bash title="Interactive motor jog with live signal"
sudo python3 tools/motor.py interactive sudo python3 tools/motor.py interactive
``` ```
```bash title="Drive to a stored position" ```bash title="Drive to a stored position"
sudo python3 tools/motor.py goto 3 sudo python3 tools/motor.py goto 3
``` ```
```bash title="USALS GotoX (Es'hail-2 from central Texas)" ```bash title="USALS GotoX (Es'hail-2 from central Texas)"
sudo python3 tools/motor.py gotox --sat 25.9 --lon -97.5 sudo python3 tools/motor.py gotox --sat 25.9 --lon -97.5
``` ```
## Subcommands ## Subcommands
| Command | Description | | Command | Description |
|---------|-------------| |---------|-------------|
| `halt` | Emergency stop the motor | | `halt` | Emergency stop the motor |
| `east [--steps N]` | Drive east (continuous or N steps) | | `east [--steps N]` | Drive east (continuous or N steps) |
| `west [--steps N]` | Drive west (continuous or N steps) | | `west [--steps N]` | Drive west (continuous or N steps) |
| `goto SLOT` | Recall stored position (0 = reference) | | `goto SLOT` | Recall stored position (0 = reference) |
| `store SLOT` | Store current position in slot (1-255) | | `store SLOT` | Store current position in slot (1-255) |
| `gotox --sat LON --lon LON` | USALS GotoX with calculated rotation angle | | `gotox --sat LON --lon LON` | USALS GotoX with calculated rotation angle |
| `limit east\|west` | Set east or west movement limit | | `limit east\|west` | Set east or west movement limit |
| `nolimits` | Disable movement limits | | `nolimits` | Disable movement limits |
| `raw HEX` | Send raw DiSEqC bytes (e.g. `E0 31 60`) | | `raw HEX` | Send raw DiSEqC bytes (e.g. `E0 31 60`) |
| `interactive` | Keyboard-driven jog with live signal display | | `interactive` | Keyboard-driven jog with live signal display |
## Interactive Mode ## Interactive Mode
The `interactive` subcommand turns the terminal into a real-time motor controller optimized for dish alignment. No menus, no prompts — just directional input with instant signal feedback. The `interactive` subcommand turns the terminal into a real-time motor controller optimized for dish alignment. No menus, no prompts — just directional input with instant signal feedback.
| Key | Action | | Key | Action |
|-----|--------| |-----|--------|
| <kbd>Left</kbd> / <kbd>h</kbd> | Jog west | | <kbd>Left</kbd> / <kbd>h</kbd> | Jog west |
| <kbd>Right</kbd> / <kbd>l</kbd> | Jog east | | <kbd>Right</kbd> / <kbd>l</kbd> | Jog east |
| <kbd>Space</kbd> | Halt motor | | <kbd>Space</kbd> | Halt motor |
| <kbd>1</kbd><kbd>9</kbd> | Recall stored position | | <kbd>1</kbd><kbd>9</kbd> | Recall stored position |
| <kbd>s</kbd> | Store current position (prompts for slot) | | <kbd>s</kbd> | Store current position (prompts for slot) |
| <kbd>g</kbd> | USALS GotoX (prompts for coordinates) | | <kbd>g</kbd> | USALS GotoX (prompts for coordinates) |
| <kbd>q</kbd> | Quit (motor auto-halts on exit) | | <kbd>q</kbd> | Quit (motor auto-halts on exit) |
Signal readings update at ~2 Hz, showing SNR, AGC power, and lock status. The display uses ANSI color to distinguish locked (green) from unlocked (red) states. Signal readings update at ~2 Hz, showing SNR, AGC power, and lock status. The display uses ANSI color to distinguish locked (green) from unlocked (red) states.
### Safety Features ### Safety Features
- **30-second auto-halt** — continuous jog stops automatically after 30 seconds to prevent mechanical damage - **30-second auto-halt** — continuous jog stops automatically after 30 seconds to prevent mechanical damage
- **Exit handler** — motor is halted via `atexit` if the process terminates unexpectedly - **Exit handler** — motor is halted via `atexit` if the process terminates unexpectedly
- **Limit enforcement** — DiSEqC 1.2 hardware limits are respected when set - **Limit enforcement** — DiSEqC 1.2 hardware limits are respected when set
<Aside type="caution"> <Aside type="caution">
The motor continues to drive until explicitly halted. If the SkyWalker-1 loses USB power during a jog, the motor will keep moving until it hits a hardware limit. Always set east/west limits before extended use. The motor continues to drive until explicitly halted. If the SkyWalker-1 loses USB power during a jog, the motor will keep moving until it hits a hardware limit. Always set east/west limits before extended use.
</Aside> </Aside>
## USALS GotoX ## USALS GotoX
The `gotox` subcommand calculates the optimal motor rotation angle using the USALS (Universal Satellites Automatic Location System) algorithm and sends a DiSEqC 1.3 GotoX command. The `gotox` subcommand calculates the optimal motor rotation angle using the USALS (Universal Satellites Automatic Location System) algorithm and sends a DiSEqC 1.3 GotoX command.
```bash title="Calculate and drive to Es'hail-2 (QO-100)" ```bash title="Calculate and drive to Es'hail-2 (QO-100)"
sudo python3 tools/motor.py gotox --sat 25.9 --lon -97.5 sudo python3 tools/motor.py gotox --sat 25.9 --lon -97.5
# Output: Angle: 72.4 deg East — sending GotoX # Output: Angle: 72.4 deg East — sending GotoX
``` ```
The angle calculation accounts for: The angle calculation accounts for:
- Observer longitude (negative = West) - Observer longitude (negative = West)
- Satellite longitude (positive = East) - Satellite longitude (positive = East)
- Geostationary orbit geometry at 35,786 km altitude - Geostationary orbit geometry at 35,786 km altitude
<Aside type="tip"> <Aside type="tip">
For QO-100 reception from North America, the motor angle is extreme (~70+ degrees East). Verify your positioner has sufficient travel range before issuing the command. For QO-100 reception from North America, the motor angle is extreme (~70+ degrees East). Verify your positioner has sufficient travel range before issuing the command.
</Aside> </Aside>
## DiSEqC 1.2 Protocol ## DiSEqC 1.2 Protocol
All motor commands use DiSEqC 1.2 (EN 50494) framing transmitted through the SkyWalker-1's Manchester encoder. The firmware generates the 22 kHz modulated waveform with correct timing: All motor commands use DiSEqC 1.2 (EN 50494) framing transmitted through the SkyWalker-1's Manchester encoder. The firmware generates the 22 kHz modulated waveform with correct timing:
| Command | DiSEqC Bytes | Description | | Command | DiSEqC Bytes | Description |
|---------|-------------|-------------| |---------|-------------|-------------|
| Halt | `E0 31 60` | Stop motor movement | | Halt | `E0 31 60` | Stop motor movement |
| Drive East | `E0 31 68 00` | Continuous east (00 = no step limit) | | Drive East | `E0 31 68 00` | Continuous east (00 = no step limit) |
| Drive West | `E0 31 69 00` | Continuous west | | Drive West | `E0 31 69 00` | Continuous west |
| Store Position | `E0 31 6A NN` | Save current position to slot NN | | Store Position | `E0 31 6A NN` | Save current position to slot NN |
| Goto Position | `E0 31 6B NN` | Drive to stored position NN | | Goto Position | `E0 31 6B NN` | Drive to stored position NN |
| Set East Limit | `E0 31 66 00` | Set current position as east limit | | Set East Limit | `E0 31 66 00` | Set current position as east limit |
| Set West Limit | `E0 31 66 01` | Set current position as west limit | | Set West Limit | `E0 31 66 01` | Set current position as west limit |
| Disable Limits | `E0 31 63` | Remove movement limits | | Disable Limits | `E0 31 63` | Remove movement limits |
| GotoX | `E0 31 6E HH LL` | USALS rotation (angle encoded as 2 bytes) | | GotoX | `E0 31 6E HH LL` | USALS rotation (angle encoded as 2 bytes) |
The `raw` subcommand accepts any hex string for advanced DiSEqC messaging beyond the built-in commands. The `raw` subcommand accepts any hex string for advanced DiSEqC messaging beyond the built-in commands.
## See Also ## See Also
- [SkyWalker TUI — Motor Screen](/tools/tui/#motor-control) — graphical motor control with signal gauge - [SkyWalker TUI — Motor Screen](/tools/tui/#motor-control) — graphical motor control with signal gauge
- [DiSEqC Protocol](/lnb-diseqc/diseqc-protocol/) — protocol specification and Manchester encoding details - [DiSEqC Protocol](/lnb-diseqc/diseqc-protocol/) — protocol specification and Manchester encoding details
- [QO-100 DATV Reception](/guides/qo100-datv/) — using motor control for QO-100 dish pointing - [QO-100 DATV Reception](/guides/qo100-datv/) — using motor control for QO-100 dish pointing

View File

@ -1,260 +1,260 @@
--- ---
title: RF Test Bench title: RF Test Bench
description: Automated CW injection testing with NanoVNA, HMC472A digital attenuator, and SkyWalker-1 receiver. description: Automated CW injection testing with NanoVNA, HMC472A digital attenuator, and SkyWalker-1 receiver.
--- ---
import { Aside, Badge, Card, CardGrid, Steps, Tabs, TabItem } from '@astrojs/starlight/components'; import { Aside, Badge, Card, CardGrid, Steps, Tabs, TabItem } from '@astrojs/starlight/components';
<Badge text="tools/rf_testbench.py" variant="note" /> <Badge text="tools/rf_testbench.py" variant="note" />
The `rf_testbench.py` tool turns a NanoVNA, an HMC472A digital attenuator, and the SkyWalker-1 into The `rf_testbench.py` tool turns a NanoVNA, an HMC472A digital attenuator, and the SkyWalker-1 into
an automated RF test bench. It injects CW signals at known frequencies and power levels, then an automated RF test bench. It injects CW signals at known frequencies and power levels, then
measures the receiver's response — characterizing AGC linearity, IF band flatness, frequency measures the receiver's response — characterizing AGC linearity, IF band flatness, frequency
accuracy, sensitivity, and BPSK mode 9 behavior. accuracy, sensitivity, and BPSK mode 9 behavior.
## Hardware Setup ## Hardware Setup
<Steps> <Steps>
1. **NanoVNA CH0 output** (SMA) connects to a **DC blocker** (SMA inline, required) 1. **NanoVNA CH0 output** (SMA) connects to a **DC blocker** (SMA inline, required)
2. **DC blocker output** connects to the **HMC472A RF IN** (SMA) 2. **DC blocker output** connects to the **HMC472A RF IN** (SMA)
3. **HMC472A RF OUT** (SMA) connects via **SMA-to-F adapter** to the **SkyWalker-1 F-connector** 3. **HMC472A RF OUT** (SMA) connects via **SMA-to-F adapter** to the **SkyWalker-1 F-connector**
4. **HMC472A ESP32-S2 controller** connected to your network (WiFi) — reachable at `http://attenuator.local` 4. **HMC472A ESP32-S2 controller** connected to your network (WiFi) — reachable at `http://attenuator.local`
5. **NanoVNA** connected via USB (for mcnanovna automation) or operated via touchscreen (manual mode) 5. **NanoVNA** connected via USB (for mcnanovna automation) or operated via touchscreen (manual mode)
</Steps> </Steps>
``` ```
NanoVNA CH0 ──→ DC Blocker ──→ HMC472A (0-31.5 dB) ──→ SMA-to-F ──→ SkyWalker-1 NanoVNA CH0 ──→ DC Blocker ──→ HMC472A (0-31.5 dB) ──→ SMA-to-F ──→ SkyWalker-1
(SMA) (SMA) REST API control adapter (F-type) (SMA) (SMA) REST API control adapter (F-type)
http://attenuator.local http://attenuator.local
``` ```
### Components ### Components
| Component | Purpose | Notes | | Component | Purpose | Notes |
|-----------|---------|-------| |-----------|---------|-------|
| NanoVNA-H (9 kHz-1.5 GHz) | CW signal source | Output ~-15 dBm at max power. Overlaps SkyWalker-1 IF band at 950-1500 MHz | | NanoVNA-H (9 kHz-1.5 GHz) | CW signal source | Output ~-15 dBm at max power. Overlaps SkyWalker-1 IF band at 950-1500 MHz |
| DC Blocker (SMA inline) | Protect NanoVNA from LNB voltage | Required — even though the tool disables LNB power, this prevents accidental damage | | DC Blocker (SMA inline) | Protect NanoVNA from LNB voltage | Required — even though the tool disables LNB power, this prevents accidental damage |
| HMC472A attenuator module | Precision level control | 0-31.5 dB in 0.5 dB steps, controlled via ESP32-S2 REST API | | HMC472A attenuator module | Precision level control | 0-31.5 dB in 0.5 dB steps, controlled via ESP32-S2 REST API |
| SMA-to-F adapter | Connector transition | 50-to-75 ohm mismatch is ~0.2 dB — negligible | | SMA-to-F adapter | Connector transition | 50-to-75 ohm mismatch is ~0.2 dB — negligible |
<Aside type="danger" title="DC blocker is required"> <Aside type="danger" title="DC blocker is required">
The SkyWalker-1 can supply 13-18V DC through the F-connector for LNB power. Although `rf_testbench.py` The SkyWalker-1 can supply 13-18V DC through the F-connector for LNB power. Although `rf_testbench.py`
disables LNB power on startup, a bug, power glitch, or running a different tool without disconnecting disables LNB power on startup, a bug, power glitch, or running a different tool without disconnecting
could send DC voltage backward through the signal path. The DC blocker prevents this from reaching could send DC voltage backward through the signal path. The DC blocker prevents this from reaching
the HMC472A and NanoVNA. the HMC472A and NanoVNA.
</Aside> </Aside>
### HMC472A Attenuator ### HMC472A Attenuator
The [HMC472A digital attenuator](https://hmc472.l.zmesh.systems/) provides programmable signal level The [HMC472A digital attenuator](https://hmc472.l.zmesh.systems/) provides programmable signal level
control via its ESP32-S2 REST API: control via its ESP32-S2 REST API:
- **Range**: 0 to 31.5 dB in 0.5 dB steps (64 discrete settings) - **Range**: 0 to 31.5 dB in 0.5 dB steps (64 discrete settings)
- **Bandwidth**: DC to 3.8 GHz (covers the full SkyWalker-1 IF range) - **Bandwidth**: DC to 3.8 GHz (covers the full SkyWalker-1 IF range)
- **Insertion loss**: 1.4-1.9 dB typical - **Insertion loss**: 1.4-1.9 dB typical
- **Control**: HTTP REST — `POST /set {"attenuation_db": 10.5}` - **Control**: HTTP REST — `POST /set {"attenuation_db": 10.5}`
- **Switching speed**: 60 ns (faster than any measurement cycle) - **Switching speed**: 60 ns (faster than any measurement cycle)
The tool communicates with the attenuator at `http://attenuator.local` by default. Override with The tool communicates with the attenuator at `http://attenuator.local` by default. Override with
`--attenuator http://10.0.0.50` if your device has a different address. `--attenuator http://10.0.0.50` if your device has a different address.
### NanoVNA Frequency Overlap ### NanoVNA Frequency Overlap
The NanoVNA-H (HW3.7) covers 9 kHz to 1.5 GHz. The SkyWalker-1's IF range is 950-2150 MHz. The NanoVNA-H (HW3.7) covers 9 kHz to 1.5 GHz. The SkyWalker-1's IF range is 950-2150 MHz.
The **overlapping usable range is 950-1500 MHz** — the lower portion of the IF band. This is The **overlapping usable range is 950-1500 MHz** — the lower portion of the IF band. This is
sufficient for characterizing the tuner and AGC, and includes the 1420 MHz hydrogen line region. sufficient for characterizing the tuner and AGC, and includes the 1420 MHz hydrogen line region.
For testing above 1500 MHz, a different signal source (bladeRF, signal generator) would be needed. For testing above 1500 MHz, a different signal source (bladeRF, signal generator) would be needed.
## Calibration ## Calibration
Before running quantitative tests, characterize the signal path loss: Before running quantitative tests, characterize the signal path loss:
<Steps> <Steps>
1. Disconnect the SkyWalker-1 end of the cable 1. Disconnect the SkyWalker-1 end of the cable
2. Connect: **NanoVNA CH0** → DC blocker → HMC472A (set to 0 dB) → cable → **NanoVNA CH1** 2. Connect: **NanoVNA CH0** → DC blocker → HMC472A (set to 0 dB) → cable → **NanoVNA CH1**
3. Run an S21 sweep from 950 to 1500 MHz using mcnanovna or the NanoVNA touchscreen 3. Run an S21 sweep from 950 to 1500 MHz using mcnanovna or the NanoVNA touchscreen
4. Export as CSV with columns `freq_mhz` and `s21_db` (or `frequency_hz` and `loss_db`) 4. Export as CSV with columns `freq_mhz` and `s21_db` (or `frequency_hz` and `loss_db`)
5. Pass to `rf_testbench.py` with `--cal path_loss.csv` 5. Pass to `rf_testbench.py` with `--cal path_loss.csv`
</Steps> </Steps>
The tool interpolates the measured path loss at each test frequency and subtracts it from AGC The tool interpolates the measured path loss at each test frequency and subtracts it from AGC
readings. Without a calibration file, raw AGC values are still reported — useful for relative readings. Without a calibration file, raw AGC values are still reported — useful for relative
measurements but not calibrated to absolute power. measurements but not calibrated to absolute power.
<Aside type="tip" title="HMC472A insertion loss"> <Aside type="tip" title="HMC472A insertion loss">
The HMC472A adds 1.4-1.9 dB of insertion loss even at 0 dB attenuation setting. The calibration The HMC472A adds 1.4-1.9 dB of insertion loss even at 0 dB attenuation setting. The calibration
sweep captures this automatically since the signal passes through the attenuator during the S21 sweep captures this automatically since the signal passes through the attenuator during the S21
measurement. measurement.
</Aside> </Aside>
## Prerequisites ## Prerequisites
- **SkyWalker-1** with [custom firmware v3.02+](/firmware/custom-v302/) (for `tune_monitor` command) - **SkyWalker-1** with [custom firmware v3.02+](/firmware/custom-v302/) (for `tune_monitor` command)
- **HMC472A** attenuator with ESP32-S2 controller on the network - **HMC472A** attenuator with ESP32-S2 controller on the network
- **NanoVNA-H** (manual mode works with any VNA; auto mode requires [mcnanovna](https://git.supported.systems/rf/mcnanovna)) - **NanoVNA-H** (manual mode works with any VNA; auto mode requires [mcnanovna](https://git.supported.systems/rf/mcnanovna))
- **Python 3.10+** with `pyusb` installed - **Python 3.10+** with `pyusb` installed
- **DC blocker** (SMA inline) - **DC blocker** (SMA inline)
- **SMA-to-F adapter** - **SMA-to-F adapter**
## Test Descriptions ## Test Descriptions
### AGC Power Linearity ### AGC Power Linearity
```bash ```bash
python tools/rf_testbench.py agc-linearity --freq 1200 python tools/rf_testbench.py agc-linearity --freq 1200
``` ```
Injects CW at a fixed frequency while sweeping the HMC472A from 0 to 31.5 dB in 0.5 dB steps. Injects CW at a fixed frequency while sweeping the HMC472A from 0 to 31.5 dB in 0.5 dB steps.
At each attenuation level, the SkyWalker-1 reports AGC1, AGC2, and derived power. This maps the At each attenuation level, the SkyWalker-1 reports AGC1, AGC2, and derived power. This maps the
**AGC transfer function** — how the receiver's automatic gain control responds to known changes **AGC transfer function** — how the receiver's automatic gain control responds to known changes
in input power. in input power.
The output shows whether the AGC is linear, where it saturates, and its effective dynamic range. The output shows whether the AGC is linear, where it saturates, and its effective dynamic range.
With 64 measurement points across 31.5 dB, the resolution is high enough to reveal nonlinearities With 64 measurement points across 31.5 dB, the resolution is high enough to reveal nonlinearities
in the BCM3440 tuner's gain control loop. in the BCM3440 tuner's gain control loop.
### IF Band Flatness ### IF Band Flatness
```bash ```bash
python tools/rf_testbench.py band-flatness --start 950 --stop 1500 --step 10 python tools/rf_testbench.py band-flatness --start 950 --stop 1500 --step 10
``` ```
Sweeps the NanoVNA CW frequency across the IF band while keeping the HMC472A at a fixed Sweeps the NanoVNA CW frequency across the IF band while keeping the HMC472A at a fixed
attenuation (10 dB default). At each frequency, the SkyWalker-1 tunes and reads AGC power. attenuation (10 dB default). At each frequency, the SkyWalker-1 tunes and reads AGC power.
The result reveals: The result reveals:
- **Tuner gain slope**: the BCM3440 may have more gain at some frequencies than others - **Tuner gain slope**: the BCM3440 may have more gain at some frequencies than others
- **Passband ripple**: resonances or nulls in the IF filter chain - **Passband ripple**: resonances or nulls in the IF filter chain
- **Cable/path frequency response**: if a calibration file is loaded, this is subtracted out - **Cable/path frequency response**: if a calibration file is loaded, this is subtracted out
### Frequency Accuracy ### Frequency Accuracy
```bash ```bash
python tools/rf_testbench.py freq-accuracy --freqs 1000,1100,1200,1300,1400 python tools/rf_testbench.py freq-accuracy --freqs 1000,1100,1200,1300,1400
``` ```
At each test frequency, the NanoVNA injects CW while the SkyWalker-1 runs a narrow spectrum At each test frequency, the NanoVNA injects CW while the SkyWalker-1 runs a narrow spectrum
sweep (+/- 5 MHz) around the expected frequency. The detected power peak is compared against the sweep (+/- 5 MHz) around the expected frequency. The detected power peak is compared against the
injected frequency. injected frequency.
This characterizes the **BCM3440 tuner's frequency accuracy** — how much the actual tuned This characterizes the **BCM3440 tuner's frequency accuracy** — how much the actual tuned
frequency differs from the commanded frequency. The error may be systematic (constant offset) frequency differs from the commanded frequency. The error may be systematic (constant offset)
or frequency-dependent. or frequency-dependent.
### Minimum Detectable Signal ### Minimum Detectable Signal
```bash ```bash
python tools/rf_testbench.py mds --freq 1200 python tools/rf_testbench.py mds --freq 1200
``` ```
First measures the noise floor with maximum attenuation (31.5 dB). Then injects CW and steps First measures the noise floor with maximum attenuation (31.5 dB). Then injects CW and steps
the HMC472A from 0 dB upward in 1 dB increments until the signal drops below 3-sigma above the HMC472A from 0 dB upward in 1 dB increments until the signal drops below 3-sigma above
the noise floor. the noise floor.
The attenuation level where the signal disappears, combined with the NanoVNA output power The attenuation level where the signal disappears, combined with the NanoVNA output power
(~-15 dBm), gives an approximate **minimum detectable signal level** in dBm. (~-15 dBm), gives an approximate **minimum detectable signal level** in dBm.
### BPSK Mode 9 CW Probe ### BPSK Mode 9 CW Probe
```bash ```bash
python tools/rf_testbench.py bpsk-probe --freq 1200 python tools/rf_testbench.py bpsk-probe --freq 1200
``` ```
An exploratory test that tunes the SkyWalker-1 in **BPSK mode (index 9)** — the same Viterbi An exploratory test that tunes the SkyWalker-1 in **BPSK mode (index 9)** — the same Viterbi
rate 1/2 K=7 inner FEC used by GOES LRIT. A CW carrier has no modulation, so the demodulator rate 1/2 K=7 inner FEC used by GOES LRIT. A CW carrier has no modulation, so the demodulator
shouldn't acquire lock, but the AGC and carrier recovery behavior is informative. shouldn't acquire lock, but the AGC and carrier recovery behavior is informative.
Tests several symbol rates (293,883 sps matching LRIT, plus 500K, 1M, and 5M) and compares Tests several symbol rates (293,883 sps matching LRIT, plus 500K, 1M, and 5M) and compares
against QPSK mode 0 at the same frequency. This establishes a baseline for what mode 9 reports against QPSK mode 0 at the same frequency. This establishes a baseline for what mode 9 reports
with an unmodulated carrier — useful context for future modulated-signal experiments with a with an unmodulated carrier — useful context for future modulated-signal experiments with a
bladeRF. bladeRF.
## Options ## Options
| Flag | Default | Description | | Flag | Default | Description |
|------|---------|-------------| |------|---------|-------------|
| `--attenuator` | `http://attenuator.local` | HMC472A REST API base URL | | `--attenuator` | `http://attenuator.local` | HMC472A REST API base URL |
| `--nanovna` | `auto` | NanoVNA control: `auto` (mcnanovna) or `manual` (prompted) | | `--nanovna` | `auto` | NanoVNA control: `auto` (mcnanovna) or `manual` (prompted) |
| `--cal` | — | Path loss calibration CSV file | | `--cal` | — | Path loss calibration CSV file |
| `--settle` | 200 | Settle time in ms after changing attenuation | | `--settle` | 200 | Settle time in ms after changing attenuation |
| `--output` / `-o` | — | CSV output file | | `--output` / `-o` | — | CSV output file |
| `--verbose` / `-v` | — | Show raw USB traffic | | `--verbose` / `-v` | — | Show raw USB traffic |
### Per-Test Options ### Per-Test Options
| Test | Flag | Default | Description | | Test | Flag | Default | Description |
|------|------|---------|-------------| |------|------|---------|-------------|
| `agc-linearity` | `--freq` | 1200 | Test frequency in MHz | | `agc-linearity` | `--freq` | 1200 | Test frequency in MHz |
| `band-flatness` | `--start` | 950 | Start frequency in MHz | | `band-flatness` | `--start` | 950 | Start frequency in MHz |
| `band-flatness` | `--stop` | 1500 | Stop frequency in MHz | | `band-flatness` | `--stop` | 1500 | Stop frequency in MHz |
| `band-flatness` | `--step` | 10 | Frequency step in MHz | | `band-flatness` | `--step` | 10 | Frequency step in MHz |
| `freq-accuracy` | `--freqs` | 1000,1100,1200,1300,1400 | Comma-separated test frequencies | | `freq-accuracy` | `--freqs` | 1000,1100,1200,1300,1400 | Comma-separated test frequencies |
| `mds` | `--freq` | 1200 | Test frequency in MHz | | `mds` | `--freq` | 1200 | Test frequency in MHz |
| `bpsk-probe` | `--freq` | 1200 | Test frequency in MHz | | `bpsk-probe` | `--freq` | 1200 | Test frequency in MHz |
## CSV Output Format ## CSV Output Format
All tests write the same CSV format when `--output` is specified: All tests write the same CSV format when `--output` is specified:
| Column | Description | | Column | Description |
|--------|-------------| |--------|-------------|
| `timestamp` | ISO 8601 UTC timestamp | | `timestamp` | ISO 8601 UTC timestamp |
| `test_name` | Test identifier (agc_linearity, band_flatness, freq_accuracy, mds, bpsk_probe) | | `test_name` | Test identifier (agc_linearity, band_flatness, freq_accuracy, mds, bpsk_probe) |
| `freq_mhz` | Frequency in MHz | | `freq_mhz` | Frequency in MHz |
| `atten_db` | HMC472A attenuation setting in dB | | `atten_db` | HMC472A attenuation setting in dB |
| `agc1` | BCM3440 AGC1 register value | | `agc1` | BCM3440 AGC1 register value |
| `agc2` | BCM3440 AGC2 register value | | `agc2` | BCM3440 AGC2 register value |
| `power_db` | Derived power estimate in dB (relative) | | `power_db` | Derived power estimate in dB (relative) |
| `snr_raw` | Raw SNR register value | | `snr_raw` | Raw SNR register value |
| `snr_db` | SNR in dB | | `snr_db` | SNR in dB |
| `locked` | Demodulator lock status | | `locked` | Demodulator lock status |
| `lock_raw` | Raw lock status byte | | `lock_raw` | Raw lock status byte |
| `status` | Status byte | | `status` | Status byte |
| `notes` | Test-specific metadata | | `notes` | Test-specific metadata |
## Interpreting Results ## Interpreting Results
### AGC Linearity Curves ### AGC Linearity Curves
A well-behaved AGC should show a roughly linear relationship between attenuation (dB) and AGC A well-behaved AGC should show a roughly linear relationship between attenuation (dB) and AGC
register value. Look for: register value. Look for:
- **Linear region**: Where AGC tracks input power changes 1:1 in dB — this is the useful - **Linear region**: Where AGC tracks input power changes 1:1 in dB — this is the useful
measurement range measurement range
- **Saturation**: Where adding more signal doesn't change AGC — the tuner's front end is - **Saturation**: Where adding more signal doesn't change AGC — the tuner's front end is
compressing compressing
- **Noise floor**: Where reducing signal doesn't change AGC — the receiver's internal noise - **Noise floor**: Where reducing signal doesn't change AGC — the receiver's internal noise
dominates dominates
### Band Flatness ### Band Flatness
Ideal response is flat across the band. In practice: Ideal response is flat across the band. In practice:
- **1-3 dB variation** across 950-1500 MHz is typical for a consumer-grade tuner - **1-3 dB variation** across 950-1500 MHz is typical for a consumer-grade tuner
- **Sharp dips** may indicate cable resonances or connector issues - **Sharp dips** may indicate cable resonances or connector issues
- **Systematic slope** (gain increasing or decreasing with frequency) is common and can be - **Systematic slope** (gain increasing or decreasing with frequency) is common and can be
corrected in post-processing corrected in post-processing
### Frequency Error ### Frequency Error
Consumer satellite tuners typically have **50-200 kHz frequency accuracy**. A consistent offset Consumer satellite tuners typically have **50-200 kHz frequency accuracy**. A consistent offset
suggests LO error in the BCM3440. Frequency-dependent error suggests tuning nonlinearity. suggests LO error in the BCM3440. Frequency-dependent error suggests tuning nonlinearity.
## Mock Mode ## Mock Mode
Run with `SKYWALKER_MOCK=1` for testing without hardware: Run with `SKYWALKER_MOCK=1` for testing without hardware:
```bash ```bash
SKYWALKER_MOCK=1 python tools/rf_testbench.py agc-linearity --freq 1200 --nanovna manual SKYWALKER_MOCK=1 python tools/rf_testbench.py agc-linearity --freq 1200 --nanovna manual
``` ```
Mock mode uses built-in simulated responses for the SkyWalker-1 and HMC472A. The NanoVNA prompts Mock mode uses built-in simulated responses for the SkyWalker-1 and HMC472A. The NanoVNA prompts
are skipped. Useful for verifying command structure and CSV output format. are skipped. Useful for verifying command structure and CSV output format.
## See Also ## See Also
- [Spectrum Analysis](/tools/spectrum-analysis/) — frequency sweep techniques - [Spectrum Analysis](/tools/spectrum-analysis/) — frequency sweep techniques
- [Hydrogen 21 cm](/tools/h21cm/) — direct L-band input mode (same RF path concept) - [Hydrogen 21 cm](/tools/h21cm/) — direct L-band input mode (same RF path concept)
- [Signal Monitoring](/bcm4500/signal-monitoring/) — AGC and SNR register details - [Signal Monitoring](/bcm4500/signal-monitoring/) — AGC and SNR register details
- [HMC472A Documentation](https://hmc472.l.zmesh.systems/) — attenuator module reference - [HMC472A Documentation](https://hmc472.l.zmesh.systems/) — attenuator module reference
- [Applications & Use Cases](/guides/applications/) — RF test and measurement context - [Applications & Use Cases](/guides/applications/) — RF test and measurement context

Some files were not shown because too many files have changed in this diff Show More