Add Docker deployment config and v3.02 firmware docs

Deployment: Dockerfile (multi-stage dev/prod with Caddy static
serving), docker-compose.yml (caddy-docker-proxy labels),
Caddyfile, Makefile, .dockerignore.

Docs: v3.02 firmware page, v3.01 updates.
This commit is contained in:
Ryan Malloy 2026-02-12 23:31:55 -07:00
parent 867b304773
commit a7daecded6
7 changed files with 195 additions and 75 deletions

3
site/.dockerignore Normal file
View File

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

11
site/Caddyfile Normal file
View File

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

24
site/Dockerfile Normal file
View File

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

27
site/Makefile Normal file
View File

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

31
site/docker-compose.yml Normal file
View File

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

View File

@ -1,16 +1,13 @@
---
title: Custom Firmware v3.01v3.02
description: Open-source SDCC + fx2lib replacement firmware with diagnostic commands, spectrum sweep, blind scan, and signal monitoring modes.
title: Custom Firmware v3.01
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';
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 signal monitoring 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" />
| Version | Date | New Commands | Purpose |
|---------|------|-------------|---------|
| v3.01.0 | 2026-02-12 | `0xB0`--`0xB6` | Spectrum sweep, raw demod access, blind scan, hardware diagnostics |
| v3.02.0 | 2026-02-12 | `0xB7`--`0xB9` | Signal monitoring, tune-and-measure, batch register read |
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
@ -128,59 +125,6 @@ EP0BUF[0] = val;
bcm_indirect_write(page, val);
```
## Signal Monitoring Commands (v3.02)
Three new commands (`0xB7`--`0xB9`) optimize the USB protocol for spectrum analysis and real-time signal monitoring: <Badge text="v3.02" variant="success" />
| Command | Name | Direction | Payload | Purpose |
|---------|------|-----------|---------|---------|
| `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 |
| `0xB9` | MULTI_REG_READ | IN | 1--64 bytes | Batch read contiguous indirect registers |
### 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.
```c title="SIGNAL_MONITOR response format (8 bytes)"
Bytes 0-1: SNR (u16 LE, indirect regs 0x00-0x01, dBu × 256)
Bytes 2-3: AGC1 (u16 LE, indirect regs 0x02-0x03)
Bytes 4-5: AGC2 (u16 LE, indirect regs 0x04-0x05)
Byte 6: Lock (direct reg 0xA4, bit 5 = locked)
Byte 7: Status (direct reg 0xA2)
```
Enables ~50 Hz polling for real-time dish alignment feedback.
### Tune Monitor (0xB8)
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:
```c title="TUNE_MONITOR protocol"
// Phase 1: OUT (0x40) — host sends 10-byte tune payload
// wValue = dwell_ms (1-255), firmware tunes, waits, reads signal
// Phase 2: IN (0xC0) — host reads 10-byte result
// Bytes 0-5: SNR(2) + AGC1(2) + AGC2(2)
// Byte 6: lock, Byte 7: status
// Bytes 8-9: dwell_ms echo (u16 LE)
```
<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.
</Aside>
### 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 ~64× speedup for register exploration.
```c title="MULTI_REG_READ parameters"
wValue = start register number
wIndex = count (1-64)
Returns: count bytes, one per register
```
## 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.
@ -308,21 +252,21 @@ Initial state after `TD_Init()`:
## Differences from Stock Firmware
| Feature | Stock v2.06 | Custom v3.01 | Custom v3.02 |
|---------|-------------|--------------|--------------|
| Toolchain | Unknown (proprietary) | SDCC + fx2lib (open source) | Same |
| I2C timeout | None (infinite spin) | 6000-count (~5 ms) | Same |
| Boot diagnostics | None | Incremental debug modes | Same |
| Custom commands | None | 7 (`0xB0`--`0xB6`) | 10 (`0xB0`--`0xB9`) |
| Spectrum sweep | Not possible | `0xB0` via EP2 bulk | `0xB8` via control EP (host-driven) |
| Blind scan | Not possible | `0xB3` with SR sweep | Same |
| Signal monitoring | 3 USB transfers | Same as stock | 1 transfer (`0xB7`, 8 bytes) |
| Batch register read | 1 reg per transfer | Same | 64 regs per transfer (`0xB9`) |
| Raw register access | Not possible | `0xB1`/`0xB2` | Same |
| I2C bus scan | Not possible | `0xB4` | Same |
| GPIO read | Not possible | `0xB6` | Same |
| Anti-tampering | Present (v2.13) | Removed | Removed |
| Source available | No | Yes | Yes (`firmware/skywalker1.c`) |
| Feature | Stock v2.06 | Custom v3.01 |
|---------|-------------|--------------|
| Toolchain | Unknown (proprietary) | SDCC + fx2lib (open source) |
| I2C timeout | None (infinite spin) | 6000-count (~5 ms) |
| Boot diagnostics | None | Incremental debug modes |
| Custom commands | None | 7 (`0xB0`--`0xB6`) |
| Spectrum sweep | Not possible | `0xB0` via EP2 bulk |
| Blind scan | Not possible | `0xB3` with SR sweep |
| Raw register access | Not possible | `0xB1`/`0xB2` |
| I2C bus scan | Not possible | `0xB4` |
| GPIO read | Not possible | `0xB6` |
| Anti-tampering | Present (v2.13) | Removed |
| 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.
## Tuning Implementation

View File

@ -0,0 +1,80 @@
---
title: Custom Firmware v3.02
description: Signal monitoring, tune-and-measure, and batch register read commands for real-time RF analysis.
---
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" />
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 |
|----------|-------|
| Version ID | `0x030200` |
| Date | 2026-02-12 |
| New commands | `0xB7`--`0xB9` (3 added to v3.01's 7) |
| Total custom commands | 10 (`0xB0`--`0xB9`) |
## New Commands
| Command | Name | Direction | Payload | Purpose |
|---------|------|-----------|---------|---------|
| `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 |
| `0xB9` | MULTI_REG_READ | IN | 1--64 bytes | Batch read contiguous indirect registers |
## 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.
```c title="SIGNAL_MONITOR response format (8 bytes)"
Bytes 0-1: SNR (u16 LE, indirect regs 0x00-0x01, dBu × 256)
Bytes 2-3: AGC1 (u16 LE, indirect regs 0x02-0x03)
Bytes 4-5: AGC2 (u16 LE, indirect regs 0x04-0x05)
Byte 6: Lock (direct reg 0xA4, bit 5 = locked)
Byte 7: Status (direct reg 0xA2)
```
Enables ~50 Hz polling for real-time dish alignment feedback.
## Tune Monitor (0xB8)
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:
```c title="TUNE_MONITOR protocol"
// Phase 1: OUT (0x40) — host sends 10-byte tune payload
// wValue = dwell_ms (1-255), firmware tunes, waits, reads signal
// Phase 2: IN (0xC0) — host reads 10-byte result
// Bytes 0-5: SNR(2) + AGC1(2) + AGC2(2)
// Byte 6: lock, Byte 7: status
// Bytes 8-9: dwell_ms echo (u16 LE)
```
<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.
</Aside>
## 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.
```c title="MULTI_REG_READ parameters"
wValue = start register number
wIndex = count (1-64)
Returns: count bytes, one per register
```
## What Changed from v3.01
| Feature | v3.01 | v3.02 |
|---------|-------|-------|
| Custom commands | 7 (`0xB0`--`0xB6`) | 10 (`0xB0`--`0xB9`) |
| 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) |
| Batch register read | 1 reg per transfer | 64 regs per transfer (`0xB9`) |
| 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.