Add Starlight documentation site (32 pages, 9 sidebar groups)
Astro 5 + Starlight 0.37 site at site/ with teal/steel theme. Content sourced from 14 reverse engineering docs, master reference, and custom firmware source. Includes Tabs, Badge, Steps, Aside, FileTree, and CardGrid components throughout. DiSEqC SVGs with click-to-zoom via starlight-image-zoom. All internal links validated. Pagefind search indexes all 32 pages.
This commit is contained in:
parent
f1d4f4f010
commit
b21f4957f6
42 changed files with 15635 additions and 0 deletions
135
site/src/content/docs/usb/boot-sequence.mdx
Normal file
135
site/src/content/docs/usb/boot-sequence.mdx
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
---
|
||||
title: Boot Sequence
|
||||
description: Complete power-on boot flow from USB enumeration through BCM4500 demodulator initialization.
|
||||
---
|
||||
|
||||
import { Steps, Badge, Aside } from '@astrojs/starlight/components';
|
||||
|
||||
## EEPROM Boot (Hardware)
|
||||
|
||||
The SkyWalker-1 firmware is stored in a 24Cxx-family I2C EEPROM in Cypress C2 format. On power-up, the FX2 boot ROM reads this firmware automatically -- no host interaction is required.
|
||||
|
||||
### C2 EEPROM Format
|
||||
|
||||
| Offset | Size | Field | SkyWalker-1 Value |
|
||||
|--------|------|-------|-------------------|
|
||||
| 0 | 1 | Marker | 0xC2 (external memory, large code model) |
|
||||
| 1 | 2 | VID (LE) | 0x09C0 |
|
||||
| 3 | 2 | PID (LE) | 0x0203 |
|
||||
| 5 | 2 | DID (LE) | 0x0000 |
|
||||
| 7 | 1 | Config | 0x40 (400 kHz I2C) |
|
||||
|
||||
Code segments follow the header: 2-byte length (BE) + 2-byte target address (BE) + data. Maximum segment size is 1023 bytes (FX2 I2C boot ROM buffer limit). All SkyWalker-1 variants use 10 segments.
|
||||
|
||||
The terminator is 0x80xx (high bit set) + 2-byte entry point address (0xE600 = CPUCS register).
|
||||
|
||||
## Kernel Driver Boot Flow
|
||||
|
||||
After USB enumeration, the Linux `dvb_usb_gp8psk` driver executes this initialization sequence:
|
||||
|
||||
<Steps>
|
||||
1. **GET_8PSK_CONFIG (0x80)** -- Read the [configuration status byte](/usb/config-status/). Check bit 0 (`bm8pskStarted`).
|
||||
|
||||
2. **BOOT_8PSK (0x89, wValue=1)** -- If not started, power on the BCM4500 demodulator. Then read the firmware version via **GET_FW_VERS (0x92)**.
|
||||
|
||||
3. **LOAD_BCM4500 (0x88)** -- If bit 1 (`bm8pskFW_Loaded`) is clear, load BCM4500 firmware. This only applies to Rev.1 Warm (PID 0x0201). On SkyWalker-1, this bit is always set and 0x88 returns STALL.
|
||||
|
||||
4. **START_INTERSIL (0x8A, wValue=1)** -- If bit 2 (`bmIntersilOn`) is clear, enable the LNB power supply.
|
||||
|
||||
5. **SET_DVB_MODE (0x8E, wValue=1)** -- Attempt to set DVB mode. This STALLs on all SkyWalker-1 firmware versions (the command is a no-op).
|
||||
|
||||
6. **ARM_TRANSFER (0x85, wValue=0)** -- Abort any pending MPEG-2 transfer to ensure a clean state.
|
||||
|
||||
7. **Device ready for tuning** -- The kernel driver reports the frontend as available.
|
||||
</Steps>
|
||||
|
||||
## BCM4500 Demodulator Boot (BOOT_8PSK, 0x89)
|
||||
|
||||
The BOOT_8PSK command handler powers on the BCM4500 demodulator and writes three initialization register blocks via I2C. This sequence was reverse-engineered from stock v2.06 firmware (`FUN_CODE_1D4F` + `FUN_CODE_0ddd`) and re-implemented in custom firmware v3.01.0.
|
||||
|
||||
<Steps>
|
||||
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.
|
||||
|
||||
3. **Wait for power settle** -- 30 ms delay. The power supply must reach regulation before releasing reset.
|
||||
|
||||
4. **Release RESET** -- Drive P0.5 HIGH. The BCM4500 begins its internal power-on reset (POR) and mask ROM boot sequence.
|
||||
|
||||
5. **Wait for BCM4500 POR** -- 50 ms delay. The chip needs time for its internal oscillator to stabilize and mask ROM to execute.
|
||||
|
||||
6. **I2C probe** -- Read direct register 0xA2 (status) at I2C address 0x08 to verify the chip is alive and responding. If this fails, boot aborts.
|
||||
|
||||
7. **Write init block 0** -- 7 bytes to indirect page 0, starting at register 0x06. Data: `{06 0b 17 38 9f d9 80}`.
|
||||
|
||||
8. **Write init block 1** -- 8 bytes to indirect page 0, starting at register 0x07. Data: `{07 09 39 4f 00 65 b7 10}`.
|
||||
|
||||
9. **Write init block 2** -- 3 bytes to indirect page 0, starting at register 0x0F. Data: `{0f 0c 09}`.
|
||||
|
||||
10. **Set config_status** -- OR in `BM_STARTED | BM_FW_LOADED` (0x03). Subsequent vendor commands check this flag before operating.
|
||||
</Steps>
|
||||
|
||||
Each init block is written using the BCM4500 [indirect register protocol](/bcm4500/demodulator/): page select (0xA6 = 0x00), data to 0xA7 (multi-byte with auto-increment), trailing zero to 0xA7, then commit (0xA8 = 0x03). The firmware polls 0xA8 until the command completes before proceeding.
|
||||
|
||||
**Total boot time**: approximately 90 ms (30 ms power settle + 50 ms POR delay + ~10 ms I2C transactions).
|
||||
|
||||
### Boot Results
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Boot time | ~90 ms total |
|
||||
| config_status after boot | 0x03 (STARTED + FW_LOADED) |
|
||||
| Direct registers 0xA2-0xA8 | All return 0x02 (powered, not locked -- expected without signal) |
|
||||
| Signal lock | 0x00 (no lock -- no satellite signal present) |
|
||||
|
||||
<Aside type="danger" title="I2C STOP Corruption During Boot">
|
||||
A critical bug was discovered during custom firmware development: sending `I2CS |= bmSTOP` when no I2C transaction is active (before the probe step) corrupts the FX2 I2C controller state, causing all subsequent I2C operations to fail.
|
||||
|
||||
The fix is to simply omit the spurious STOP condition. If the I2C bus is idle (as it should be after power-on), a new START condition succeeds without any bus reset.
|
||||
|
||||
See [I2C STOP Corruption Bug](/i2c/stop-corruption-bug/) for the complete root cause analysis.
|
||||
</Aside>
|
||||
|
||||
## Firmware Version Identification
|
||||
|
||||
The kernel reads the firmware version on boot via GET_FW_VERS (0x92) and logs it:
|
||||
|
||||
```
|
||||
gp8psk: FW Version = 2.06.4 (0x20604) Build 2007/07/13
|
||||
```
|
||||
|
||||
Kernel revision constants for hardware detection:
|
||||
|
||||
```c title="gp8psk-fe.h"
|
||||
GP8PSK_FW_REV1 = 0x020604 // v2.06.4
|
||||
GP8PSK_FW_REV2 = 0x020704 // v2.07.4
|
||||
```
|
||||
|
||||
If `fw_vers >= GP8PSK_FW_REV2`, the kernel enables Rev.2-specific code paths. The v2.10 and v2.13 firmwares are newer than either constant and trigger Rev.2 behavior.
|
||||
|
||||
## FX2 CPUCS Recovery
|
||||
|
||||
The FX2's CPUCS register at 0xE600 is accessible via the standard vendor request `bRequest=0xA0` (RAM read/write), which is handled by the FX2 boot ROM in silicon -- not by user firmware. This means firmware can be reloaded over a completely hung device without a physical USB unplug:
|
||||
|
||||
```bash title="Recover a hung device"
|
||||
sudo python3 tools/fw_load.py load firmware/build/skywalker1.ihx --wait 3
|
||||
```
|
||||
|
||||
Writing 0x01 to CPUCS halts the CPU. New code is written to RAM. Writing 0x00 restarts it. The device re-enumerates with the new firmware.
|
||||
|
||||
## Custom Debug Boot Modes (v3.01.0)
|
||||
|
||||
The custom firmware extends BOOT_8PSK (0x89) with incremental debug modes for isolating boot failures:
|
||||
|
||||
| wValue | Action | Purpose |
|
||||
|--------|--------|---------|
|
||||
| 0x80 | No-op: return `config_status` and `boot_stage` | Status check without side effects |
|
||||
| 0x81 | GPIO + power + delays only (no I2C) | Test power sequencing |
|
||||
| 0x82 | GPIO + power + I2C probe | Test I2C after power-on |
|
||||
| 0x83 | GPIO + power + probe + init block 0 | Test first register write |
|
||||
| 0x84 | I2C probe only (chip already powered) | Isolate I2C from power sequencing |
|
||||
| 0x85 | Same as 0x82 without bmSTOP | Confirmed the STOP corruption bug |
|
||||
| 0x01 | Full boot (production) | Normal operation |
|
||||
| 0x00 | Shutdown | Power down demodulator |
|
||||
|
||||
These modes were instrumental in identifying the [I2C STOP corruption bug](/i2c/stop-corruption-bug/) -- mode 0x82 (with bmSTOP) failed while mode 0x85 (without bmSTOP) succeeded, pinpointing the exact cause.
|
||||
79
site/src/content/docs/usb/config-status.mdx
Normal file
79
site/src/content/docs/usb/config-status.mdx
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
title: Configuration Status Byte
|
||||
description: Bit-field breakdown of the configuration status byte returned by GET_8PSK_CONFIG (0x80).
|
||||
---
|
||||
|
||||
import { Badge, Aside } from '@astrojs/starlight/components';
|
||||
|
||||
The configuration status byte is returned by the GET_8PSK_CONFIG vendor command (0x80) and reflects the current device state. The kernel driver checks these bits during initialization to determine which boot steps have already completed.
|
||||
|
||||
## Bit Field Map
|
||||
|
||||
| Bit | Mask | Name | Meaning |
|
||||
|-----|------|------|---------|
|
||||
| 7 | 0x80 | bmArmed | MPEG-2 stream transfer armed / GPIF active |
|
||||
| 6 | 0x40 | bmDCtuned | DC offset tuning complete (set for DCII modes) |
|
||||
| 5 | 0x20 | bmSEL18V | 18V LNB voltage selected (else 13V) |
|
||||
| 4 | 0x10 | bm22kHz | 22 kHz tone active |
|
||||
| 3 | 0x08 | bmDVBmode | DVB mode enabled |
|
||||
| 2 | 0x04 | bmIntersilOn | LNB power supply enabled |
|
||||
| 1 | 0x02 | bm8pskFW_Loaded | BCM4500 firmware loaded |
|
||||
| 0 | 0x01 | bm8pskStarted | Device booted and running |
|
||||
|
||||
## IRAM Storage Address
|
||||
|
||||
The status byte is stored at a different IRAM address depending on firmware version:
|
||||
|
||||
| Firmware | IRAM Address |
|
||||
|----------|-------------|
|
||||
| v2.06 | 0x6D |
|
||||
| Rev.2 v2.10.4 | 0x4E |
|
||||
| v2.13 | 0x4F |
|
||||
|
||||
## Bit Details
|
||||
|
||||
### Bit 0: bm8pskStarted <Badge text="0x01" variant="note" />
|
||||
|
||||
Set when BOOT_8PSK (0x89, wValue=1) completes successfully. The kernel driver checks this bit first. If clear, it sends BOOT_8PSK to power on the demodulator.
|
||||
|
||||
### Bit 1: bm8pskFW_Loaded <Badge text="0x02" variant="note" />
|
||||
|
||||
Indicates that the BCM4500 firmware has been loaded. On the SkyWalker-1, the BCM4500 runs from internal mask ROM, so this bit is **always set** after boot. The kernel driver checks this to decide whether to send LOAD_BCM4500 (0x88), which STALLs on the SkyWalker-1 since it is unnecessary.
|
||||
|
||||
### Bit 2: bmIntersilOn <Badge text="0x04" variant="note" />
|
||||
|
||||
Set when START_INTERSIL (0x8A, wValue=1) enables the LNB power supply. The name "Intersil" refers to the LNB voltage regulator IC manufacturer.
|
||||
|
||||
### Bit 3: bmDVBmode <Badge text="0x08" variant="note" />
|
||||
|
||||
Set when DVB-S mode is enabled via SET_DVB_MODE (0x8E). On SkyWalker-1, this command STALLs -- the bit is managed internally by the tuning dispatch logic.
|
||||
|
||||
### Bit 4: bm22kHz <Badge text="0x10" variant="note" />
|
||||
|
||||
Reflects the current state of the 22 kHz tone (SET_22KHZ_TONE, 0x8C). Set when the tone is active (high band), clear when inactive (low band).
|
||||
|
||||
### Bit 5: bmSEL18V <Badge text="0x20" variant="note" />
|
||||
|
||||
Reflects the current LNB voltage selection (SET_LNB_VOLTAGE, 0x8B). Set for 18V (horizontal/circular-left), clear for 13V (vertical/circular-right).
|
||||
|
||||
### Bit 6: bmDCtuned <Badge text="0x40" variant="note" />
|
||||
|
||||
Set when tuning to a Digicipher II (DCII) modulation mode. Cleared for all other modulation types (DVB-S, Turbo, DSS, BPSK). The tuning dispatch logic manages this bit during TUNE_8PSK (0x86) processing.
|
||||
|
||||
### Bit 7: bmArmed <Badge text="0x80" variant="note" />
|
||||
|
||||
Set when ARM_TRANSFER (0x85, wValue=1) starts the MPEG-2 transport stream. Cleared when ARM_TRANSFER (0x85, wValue=0) stops it. While set, the [GPIF engine](/bcm4500/gpif-streaming/) is continuously reading data from the BCM4500 into the EP2 FIFO.
|
||||
|
||||
## Typical Values
|
||||
|
||||
| State | Value | Bits Set |
|
||||
|-------|-------|----------|
|
||||
| After power-on (before boot) | 0x00 | None |
|
||||
| After BOOT_8PSK | 0x03 | bm8pskStarted + bm8pskFW_Loaded |
|
||||
| After LNB enable + 18V + tone | 0x37 | Started + FW + Intersil + 18V + 22kHz |
|
||||
| Streaming DVB-S | 0xB7 | Above + bmArmed |
|
||||
| Streaming DCII | 0xF7 | Above + bmDCtuned |
|
||||
|
||||
<Aside type="note" title="Kernel Driver Behavior">
|
||||
The kernel driver reads this byte during initialization and uses it to skip already-completed steps. On a warm reboot (without USB disconnect), some bits may already be set from the previous session, causing the driver to skip BOOT_8PSK, START_INTERSIL, or LOAD_BCM4500 as appropriate.
|
||||
</Aside>
|
||||
105
site/src/content/docs/usb/interface.mdx
Normal file
105
site/src/content/docs/usb/interface.mdx
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
---
|
||||
title: USB Interface
|
||||
description: USB VID/PID table, endpoint map, descriptors, and warm boot behavior for the SkyWalker-1.
|
||||
---
|
||||
|
||||
import { Badge, Aside } from '@astrojs/starlight/components';
|
||||
|
||||
## VID/PID Table
|
||||
|
||||
All Genpix products share USB Vendor ID `0x09C0`:
|
||||
|
||||
| PID | Product | State | Notes |
|
||||
|-----|---------|-------|-------|
|
||||
| 0x0200 | 8PSK-to-USB2 Rev.1 | <Badge text="Cold" variant="caution" /> | Requires FW01 upload to RAM |
|
||||
| 0x0201 | 8PSK-to-USB2 Rev.1 | <Badge text="Warm" variant="success" /> | Requires FW02 (BCM4500 firmware) |
|
||||
| 0x0202 | 8PSK-to-USB2 Rev.2 | <Badge text="Warm" variant="success" /> | Boots from EEPROM |
|
||||
| 0x0203 | **SkyWalker-1** | <Badge text="Warm" variant="success" /> | Boots from EEPROM |
|
||||
| 0x0204 | SkyWalker-1 (alternate) | <Badge text="Warm" variant="success" /> | Boots from EEPROM |
|
||||
| 0x0205 | SkyWalker-2 | -- | Not in kernel 6.16.5 |
|
||||
| 0x0206 | SkyWalker CW3K | <Badge text="Warm" variant="success" /> | Requires CW3K_INIT (0x9D) |
|
||||
|
||||
PID `0x0203` was added to the Linux kernel `dvb_usb_gp8psk` device table after v6.6.1.
|
||||
|
||||
## Endpoint Map
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Control endpoint | EP0 (default pipe, vendor requests) |
|
||||
| Bulk IN endpoint | EP2 (address 0x82) -- MPEG-2 transport stream |
|
||||
| Generic bulk CTRL endpoint | 0x01 (BCM4500 FW02 upload, Rev.1 only) |
|
||||
|
||||
## Streaming Properties
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| URB count | 7 |
|
||||
| URB buffer size | 8192 bytes each |
|
||||
| Stream type | USB_BULK |
|
||||
| FX2 controller type | CYPRESS_FX2 |
|
||||
|
||||
## EP2 Endpoint Configuration
|
||||
|
||||
```c title="EP2CFG Register (0xE610)"
|
||||
EP2CFG = 0xE2; // valid=1, dir=IN, type=BULK, size=512, buf=DOUBLE
|
||||
```
|
||||
|
||||
| Bit | Value | Meaning |
|
||||
|-----|-------|---------|
|
||||
| 7 (VALID) | 1 | Endpoint enabled |
|
||||
| 6 (DIR) | 1 | IN (device to host) |
|
||||
| 5:4 (TYPE) | 10 | Bulk transfer |
|
||||
| 3 (SIZE) | 0 | 512-byte packets |
|
||||
| 1:0 (BUF) | 10 | Double-buffered |
|
||||
|
||||
EP4, EP6, and EP8 are disabled (`&= ~bmVALID`). Only EP2 is used for data streaming.
|
||||
|
||||
## Warm Boot Behavior
|
||||
|
||||
The SkyWalker-1 (PID 0x0203) enumerates directly as a "warm" device. The DVB-USB framework skips firmware download when `cold_ids` is NULL. No host-side firmware files are required.
|
||||
|
||||
| Device | PID | Needs FW01? | Needs FW02? | Boot Source |
|
||||
|--------|-----|-------------|-------------|-------------|
|
||||
| Rev.1 Cold | 0x0200 | Yes | -- | RAM (empty) |
|
||||
| Rev.1 Warm | 0x0201 | No | Yes | RAM (FW01 loaded) |
|
||||
| Rev.2 | 0x0202 | No | No | EEPROM |
|
||||
| SkyWalker-1 | 0x0203 | No | No | EEPROM |
|
||||
| SkyWalker CW3K | 0x0206 | No | No | EEPROM |
|
||||
|
||||
<Aside type="note" title="Firmware Files Not Available">
|
||||
The firmware files `dvb-usb-gp8psk-01.fw` and `dvb-usb-gp8psk-02.fw` were never open-sourced or included in the `linux-firmware` package. They are only needed for the older Rev.1 hardware (PID 0x0200/0x0201), not for the SkyWalker-1.
|
||||
</Aside>
|
||||
|
||||
## USB Control Transfer Protocol
|
||||
|
||||
All vendor commands use USB control transfers with these common parameters:
|
||||
|
||||
| Parameter | Value |
|
||||
|-----------|-------|
|
||||
| bmRequestType | `USB_TYPE_VENDOR` (0x40 for OUT, 0xC0 for IN) |
|
||||
| Timeout | 2000 ms |
|
||||
| Retry | Up to 3 attempts for IN operations if partial data received |
|
||||
| Data buffer maximum | 80 bytes (kernel driver) |
|
||||
|
||||
See [Vendor Commands](/usb/vendor-commands/) for the complete command reference.
|
||||
|
||||
## Kernel Driver Modules
|
||||
|
||||
The Linux kernel uses two modules for the SkyWalker-1:
|
||||
|
||||
| Module | Function |
|
||||
|--------|----------|
|
||||
| `dvb_usb_gp8psk` | USB transport layer, device management, firmware loading |
|
||||
| `gp8psk_fe` | DVB frontend operations (demodulation, tuning, signal status) |
|
||||
|
||||
<Aside type="tip" title="Blacklisting for Development">
|
||||
When developing or testing custom firmware, blacklist both kernel modules to prevent the driver from racing with your test tools:
|
||||
|
||||
```
|
||||
# /etc/modprobe.d/blacklist-gp8psk.conf
|
||||
blacklist dvb_usb_gp8psk
|
||||
blacklist gp8psk_fe
|
||||
```
|
||||
|
||||
Then unload: `sudo modprobe -r dvb_usb_gp8psk gp8psk_fe`
|
||||
</Aside>
|
||||
177
site/src/content/docs/usb/vendor-commands.mdx
Normal file
177
site/src/content/docs/usb/vendor-commands.mdx
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
---
|
||||
title: Vendor Commands
|
||||
description: Complete USB vendor command reference with bRequest codes, parameters, and firmware version compatibility.
|
||||
---
|
||||
|
||||
import { Tabs, TabItem, Badge, Aside } from '@astrojs/starlight/components';
|
||||
|
||||
All vendor commands use USB control transfers with `USB_TYPE_VENDOR` (bmRequestType bit 6 set). The vendor command dispatcher at CODE:0056 validates `bRequest` in the range 0x80--0x9D (30 entries for v2.06/v2.13) or 0x80--0x9A (27 entries for Rev.2) and dispatches via an indexed jump table at CODE:0076.
|
||||
|
||||
<Aside type="note" title="Status Key">
|
||||
<Badge text="OK" variant="success" /> = Implemented and functional. <Badge text="STALL" variant="danger" /> = Routes to stall handler (endpoint stall returned). <Badge text="Proto" variant="caution" /> = Partial/prototype implementation. <Badge text="N/A" variant="note" /> = Command index out of range (Rev.2 only supports 0x80--0x9A). <Badge text="Changed" variant="caution" /> = Implementation differs between versions.
|
||||
</Aside>
|
||||
|
||||
<Tabs>
|
||||
<TabItem label="Documented Commands">
|
||||
|
||||
## Stock Command Table (0x80--0x9D)
|
||||
|
||||
| Cmd | Name | Dir | wValue | wIndex | wLength | Purpose | v2.06 | Rev.2 | v2.13 |
|
||||
|-----|------|-----|--------|--------|---------|---------|-------|-------|-------|
|
||||
| 0x80 | GET_8PSK_CONFIG | IN | 0 | 0 | 1 | Read [configuration status byte](/usb/config-status/) | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x81 | SET_8PSK_CONFIG | OUT | varies | 0 | 0 | Set config (reserved) | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> |
|
||||
| 0x82 | (reserved) | -- | -- | -- | -- | Reserved | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> |
|
||||
| 0x83 | I2C_WRITE | OUT | dev_addr | reg_addr | N | Write to I2C device | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x84 | I2C_READ | IN | dev_addr | reg_addr | N | Read from I2C device | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x85 | ARM_TRANSFER | OUT | 0/1 | 0 | 0 | Start (1) / stop (0) MPEG-2 stream | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x86 | TUNE_8PSK | OUT | 0 | 0 | 10 | Set [tuning parameters](/bcm4500/tuning-protocol/) | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x87 | GET_SIGNAL_STRENGTH | IN | 0 | 0 | 6 | Read [SNR and diagnostics](/bcm4500/signal-monitoring/) | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="Changed" variant="caution" /> |
|
||||
| 0x88 | LOAD_BCM4500 | OUT | 1 | 0 | 0 | Initiate BCM4500 FW download | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> |
|
||||
| 0x89 | BOOT_8PSK | IN | 0/1 | 0 | 1 | Power on (1) / off (0) demodulator | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x8A | START_INTERSIL | IN | 0/1 | 0 | 1 | Enable (1) / disable (0) LNB supply | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x8B | SET_LNB_VOLTAGE | OUT | 0/1 | 0 | 0 | 13V (0) or 18V (1) | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x8C | SET_22KHZ_TONE | OUT | 0/1 | 0 | 0 | Tone off (0) or on (1) | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x8D | SEND_DISEQC_COMMAND | OUT | msg[0] | 0 | len | DiSEqC message or tone burst | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x8E | SET_DVB_MODE | OUT | 1 | 0 | 0 | Enable DVB-S mode | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> | <Badge text="STALL" variant="danger" /> |
|
||||
| 0x8F | SET_DN_SWITCH | OUT | cmd7bit | 0 | 0 | Legacy Dish Network switch protocol | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x90 | GET_SIGNAL_LOCK | IN | 0 | 0 | 1 | Read [signal lock status](/bcm4500/signal-monitoring/) | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x92 | GET_FW_VERS | IN | 0 | 0 | 6 | Read firmware version + build date | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x93 | GET_SERIAL_NUMBER | IN | 0 | 0 | 4 | Read 4-byte serial from EEPROM | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x94 | USE_EXTRA_VOLT | OUT | 0/1 | 0 | 0 | Enable +1V LNB boost (14V/19V) | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x95 | GET_FPGA_VERS | IN | 0 | 0 | 1 | Read EEPROM hardware/platform ID | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
|
||||
### Detailed Parameter Formats
|
||||
|
||||
**0x87 GET_SIGNAL_STRENGTH**: Returns 6 bytes. Bytes 0--1 contain a 16-bit SNR value (little-endian, dBu x 256 units). Bytes 2--5 are reserved/diagnostic BCM4500 registers. Version differences: v2.06 polls 3 registers (0xA2, 0xA8, 0xA4) up to 6 times; v2.13 consolidates to 1 register with a simplified poll.
|
||||
|
||||
**0x8D SEND_DISEQC_COMMAND**: When `wLength > 0`, the payload is a standard DiSEqC message (3--6 bytes) with `wValue` set to `msg[0]` (framing byte, typically 0xE0 or 0xE1). When `wLength == 0` and `wValue == 0`, tone burst A is sent. When `wLength == 0` and `wValue != 0`, tone burst B is sent.
|
||||
|
||||
**0x8F SET_DN_SWITCH**: `wValue` carries a 7-bit Dish Network switch command (LSB-first), bit-banged on GPIO P0.4 with specific timing. The 8th bit (0x80) of the original switch command selects LNB voltage and is sent separately via SET_LNB_VOLTAGE.
|
||||
|
||||
**0x92 GET_FW_VERS**: Returns 6 bytes of hardcoded constants:
|
||||
|
||||
```c title="GET_FW_VERS Response Format"
|
||||
Byte 0: version minor_minor (e.g., 0x04)
|
||||
Byte 1: version minor (e.g., 0x06)
|
||||
Byte 2: version major (e.g., 0x02)
|
||||
Byte 3: build day (e.g., 0x0D = 13)
|
||||
Byte 4: build month (e.g., 0x07 = July)
|
||||
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]
|
||||
```
|
||||
|
||||
**0x93 GET_SERIAL_NUMBER**: Returns 4 bytes read from I2C EEPROM at device address 0x51 (7-bit), extracted at 8-bit intervals using a shift/rotate routine.
|
||||
|
||||
**0x94 USE_EXTRA_VOLT**: `wValue=1` writes 0x6A to XRAM 0xE0B6; `wValue=0` writes 0x62. The difference is bit 3 (0x08), which controls the voltage boost on the LNB power regulator.
|
||||
|
||||
**0x95 GET_FPGA_VERS**: Reads from I2C EEPROM at 0x51. Despite the name, there is no FPGA on the SkyWalker-1 -- this returns a hardware platform ID. v2.06 reads EEPROM offset 0x31 (2 bytes); v2.13/Rev.2 read offset 0x00 (1 byte).
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Debug / Internal Commands">
|
||||
|
||||
## Debug Commands (0x91, 0x96--0x98)
|
||||
|
||||
These commands are not used by any driver (Linux or Windows). They appear to be manufacturing/debug interfaces.
|
||||
|
||||
| Cmd | Name | Dir | wValue | wLength | Purpose | v2.06 | Rev.2 | v2.13 |
|
||||
|-----|------|-----|--------|---------|---------|-------|-------|-------|
|
||||
| 0x91 | I2C_ADDR_ADJUST | IN | 0=dec, 1=inc | 1 | Inc/dec internal IRAM counter | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x96 | SET_LNB_GPIO_MODE | OUT | 0/1 | 0 | Configure LNB GPIO output enables | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x97 | SET_GPIO_PINS | OUT | bitmap | 0 | Direct write to LNB GPIO pins | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x98 | GET_GPIO_STATUS | IN | 0 | 1 | Read LNB feedback GPIO pin | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> | <Badge text="OK" variant="success" /> |
|
||||
|
||||
### 0x91 I2C_ADDR_ADJUST
|
||||
|
||||
Increments (`wValue != 0`) or decrements (`wValue == 0`) an internal IRAM counter and returns its current value (1 byte). The counter lives at IRAM 0x66 (v2.06) or IRAM 0x18 (v2.13/Rev.2). Likely used for I2C address or tuner register index adjustment during development.
|
||||
|
||||
### 0x96 SET_LNB_GPIO_MODE
|
||||
|
||||
Configures GPIO output enable registers for the LNB voltage regulator hardware:
|
||||
|
||||
| Mode | v2.06/v2.13 | Rev.2 |
|
||||
|------|-------------|-------|
|
||||
| Default (wValue=0) | OEB=0xF0 | OEB=0xE7, OEA=0x9E |
|
||||
| Active (wValue=1) | IOB=(IOB & 0xF7) OR 0x06; OEB=0xFE | IOB.4 clear; P0.6, P0.0 set; OEA OR= 0x41 |
|
||||
|
||||
### 0x97 SET_GPIO_PINS
|
||||
|
||||
Direct GPIO pin write for LNB control:
|
||||
|
||||
| wValue Bit | v2.06/v2.13 Target | Rev.2 Target |
|
||||
|-----------|-------------------|-------------|
|
||||
| bit 1 | IOB.1 (Port B) | P0.6 (Port A) |
|
||||
| bit 2 | IOB.2 (Port B) | P0.0 (Port A) |
|
||||
| bit 3 | IOB.3 (Port B) | IOB.4 (Port B) |
|
||||
|
||||
### 0x98 GET_GPIO_STATUS
|
||||
|
||||
Returns 1 byte (0 or 1) from a single GPIO input pin -- likely an LNB overcurrent or power-good feedback signal:
|
||||
|
||||
| Version | Pin Read |
|
||||
|---------|----------|
|
||||
| v2.06/v2.13 | IOB.0 (Port B bit 0) |
|
||||
| Rev.2 | P0.5 (Port A bit 5) |
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Extended Commands (v2.13+)">
|
||||
|
||||
## Extended Commands (0x99--0x9D)
|
||||
|
||||
| Cmd | Name | Dir | wValue | wLength | Purpose | v2.06 | Rev.2 | v2.13 |
|
||||
|-----|------|-----|--------|---------|---------|-------|-------|-------|
|
||||
| 0x99 | GET_DEMOD_STATUS | IN | 0 | 1 | Read BCM4500 register 0xF9 | <Badge text="STALL" variant="danger" /> | <Badge text="Proto" variant="caution" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x9A | INIT_DEMOD | OUT | 0 | 0 | Trigger demod re-init (3 attempts) | <Badge text="STALL" variant="danger" /> | <Badge text="Proto" variant="caution" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x9B | (reserved) | -- | -- | -- | Reserved | <Badge text="STALL" variant="danger" /> | <Badge text="N/A" variant="note" /> | <Badge text="STALL" variant="danger" /> |
|
||||
| 0x9C | DELAY_COMMAND | OUT | delay | 0 | Host-controlled tuning delay + poll | <Badge text="STALL" variant="danger" /> | <Badge text="N/A" variant="note" /> | <Badge text="OK" variant="success" /> |
|
||||
| 0x9D | CW3K_INIT / SET_MODE_FLAG | OUT | 0/1 | 0 | CW3K init or conditional demod reset | <Badge text="OK" variant="success" /> | <Badge text="N/A" variant="note" /> | <Badge text="Changed" variant="caution" /> |
|
||||
|
||||
### Driver Usage Notes
|
||||
|
||||
- The Linux driver only sends LOAD_BCM4500 (0x88) for Rev.1 Warm (PID 0x0201). On SkyWalker-1, `bm8pskFW_Loaded` is already set and 0x88 routes to STALL.
|
||||
- The Linux driver only sends CW3K_INIT (0x9D) for SkyWalker CW3K (PID 0x0206).
|
||||
- Rev.2 supports only commands 0x80--0x9A (27 entries). Commands 0x9B--0x9D are out of range and produce undefined behavior.
|
||||
|
||||
</TabItem>
|
||||
<TabItem label="Custom Firmware">
|
||||
|
||||
## Custom Firmware Commands (0xB0--0xB6)
|
||||
|
||||
Commands added in custom firmware v3.01.0 for development and diagnostics:
|
||||
|
||||
| Cmd | Name | Dir | wValue | wIndex | wLength | Purpose |
|
||||
|-----|------|-----|--------|--------|---------|---------|
|
||||
| 0xB0 | SPECTRUM_SWEEP | OUT | 0 | 0 | 10 | Step through freq range, read SNR at each step |
|
||||
| 0xB1 | RAW_DEMOD_READ | IN | reg | 0 | 1 | Read BCM4500 indirect register |
|
||||
| 0xB2 | RAW_DEMOD_WRITE | OUT | reg | data | 0 | Write BCM4500 indirect register |
|
||||
| 0xB3 | BLIND_SCAN | OUT | 0 | 0 | 16 | Try symbol rates at given freq, report lock |
|
||||
| 0xB4 | I2C_BUS_SCAN | IN | 0 | 0 | 16 | Probe all 7-bit addresses, return 16-byte bitmap |
|
||||
| 0xB5 | I2C_RAW_READ | IN | addr7 | reg | N | Combined write-read from any I2C device |
|
||||
| 0xB6 | I2C_DIAG | IN | page | 0 | 8 | Step-by-step indirect register diagnostic |
|
||||
|
||||
### Parameter Formats
|
||||
|
||||
**0xB0 SPECTRUM_SWEEP**: 10-byte EP0 payload: `[start_freq(u32 LE kHz), stop_freq(u32 LE kHz), step_khz(u16 LE)]`. Programs BCM4500 at each frequency step, reads SNR, packs u16 LE results into EP2 bulk FIFO.
|
||||
|
||||
**0xB3 BLIND_SCAN**: 16-byte EP0 payload: `[freq_khz(u32 LE), sr_min(u32 LE sps), sr_max(u32 LE sps), sr_step(u32 LE sps)]`. Returns 8 bytes on lock `[freq_khz(4) + sr_locked(4)]` or 1 byte 0x00 if no lock found.
|
||||
|
||||
**0xB4 I2C_BUS_SCAN**: Returns a 16-byte bitmap (128 bits for addresses 0x00--0x77). Each bit set = ACK received at that 7-bit address.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Vendor Command Dispatch Mechanism
|
||||
|
||||
The dispatch logic at CODE:0056 (identical address across all stock versions):
|
||||
|
||||
```
|
||||
1. Check bmRequestType bit 6 -> vendor request?
|
||||
2. Read bRequest from SETUPDAT[1]
|
||||
3. Subtract 0x80 (command base offset)
|
||||
4. Compare against maximum: < 0x1E (v2.06/v2.13) or < 0x1B (Rev.2)
|
||||
5. If in range: double the index (2 bytes per AJMP) -> JMP @A+DPTR
|
||||
6. If out of range: route to STALL handler
|
||||
```
|
||||
|
||||
The jump table at CODE:0076 contains 2-byte AJMP instruction targets, one per command from 0x80 upward.
|
||||
Loading…
Add table
Add a link
Reference in a new issue