Add TUI documentation for F6-F8 screens and regenerate screenshots

Update tui.mdx with Device, Stream, and Config screen sections
including keyboard shortcuts, Tabs/Steps components, and safety
warnings. Update generate_screenshots.py to capture all 11 screens.
Regenerate all SVGs with current sidebar layout.
This commit is contained in:
Ryan Malloy 2026-02-14 16:24:59 -07:00
parent 567bf4d9e0
commit 0f4ba4766f
13 changed files with 2040 additions and 2939 deletions

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 81 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 85 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 92 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 85 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 80 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 596 KiB

After

Width:  |  Height:  |  Size: 474 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 64 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 86 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 322 KiB

After

Width:  |  Height:  |  Size: 95 KiB

View File

@ -1,11 +1,11 @@
---
title: SkyWalker TUI
description: Interactive terminal dashboard for spectrum analysis, transponder scanning, signal monitoring, L-band analysis, and carrier tracking.
description: Interactive terminal dashboard for spectrum analysis, transponder scanning, signal monitoring, L-band analysis, carrier tracking, device management, transport stream analysis, and hardware configuration.
---
import { Tabs, TabItem, Steps, Aside, Badge } from '@astrojs/starlight/components';
The SkyWalker TUI is a full-screen terminal dashboard built on [Textual](https://textual.textualize.io/) that wraps all five RF operating modes into a single interactive interface. Sidebar navigation, F-key shortcuts, real-time widget updates, and a dark/light theme toggle replace the separate CLI subcommands with a unified experience.
The SkyWalker TUI is a full-screen terminal dashboard built on [Textual](https://textual.textualize.io/) that wraps all eight operating modes into a single interactive interface. Five RF signal modes (Spectrum, Scan, Monitor, L-Band, Track) plus Device management, Transport Stream analysis, and hardware Config — all with sidebar navigation, F-key shortcuts, real-time widget updates, and a dark/light theme toggle.
<Badge text="Requires custom firmware v3.02.0+" variant="caution" />
@ -34,7 +34,7 @@ uv run skywalker-tui --demo
| `--demo` | Synthetic signal data — no SkyWalker-1 USB device needed |
| `--no-splash` | Skip the startup splash screen |
| `--verbose, -v` | Verbose USB logging (hardware mode only) |
| `MODE` | Initial mode: `spectrum` (default), `scan`, `monitor`, `lband`, `track` |
| `MODE` | Initial mode: `spectrum` (default), `scan`, `monitor`, `lband`, `track`, `device`, `stream`, `config` |
<Aside type="tip">
Demo mode generates realistic-looking synthetic data for every screen, making it useful for familiarization, documentation, and development without satellite hardware.
@ -51,6 +51,9 @@ Demo mode generates realistic-looking synthetic data for every screen, making it
| <kbd>F3</kbd> | Signal monitor |
| <kbd>F4</kbd> | L-Band analyzer |
| <kbd>F5</kbd> | Carrier tracker |
| <kbd>F6</kbd> | Device management |
| <kbd>F7</kbd> | Transport stream |
| <kbd>F8</kbd> | Hardware config |
| <kbd>d</kbd> | Toggle dark/light theme |
| <kbd>q</kbd> | Quit |
| <kbd>Ctrl+W</kbd> | Easter egg |
@ -127,6 +130,84 @@ Carrier/beacon tracker with timestamped logging. Tracks a single frequency and d
- Event log with timestamped lock/unlock transitions
- Frequency drift detection
### Device <Badge text="F6" variant="note" />
Firmware management, EEPROM operations, and hardware diagnostics. An identity panel at the top always shows firmware version, serial number, USB speed, and config register flags.
![Device management](../../../assets/tui/device.svg)
<Tabs>
<TabItem label="Firmware">
- FX2 RAM read at arbitrary addresses rendered as scrollable hex dump
- CPU Halt / Start controls for the Cypress FX2 microcontroller
- Non-destructive — RAM contents revert on power cycle
</TabItem>
<TabItem label="EEPROM">
- Read full 16 KB EEPROM with progress bar
- One-click backup to timestamped `.bin` file
- Flash with full safety state machine:
<Steps>
1. **C2 validation** — magic byte, VID/PID match, END marker, record parsing
2. **Auto-backup** — saves current EEPROM to timestamped file before any write
3. **3-second countdown** — ABORT button auto-focused (accidental keypress = cancel)
4. **Page write** — 16-byte pages with progress bar and circuit breaker (3 consecutive errors = abort)
5. **Byte-verify** — full readback with diff highlighting in hex view
</Steps>
</TabItem>
<TabItem label="Diagnostics">
- Boot test with mode selector (0x800x85) showing stage progression
- I2C bus scan identifying BCM4500, EEPROM, tuner, and LNB controller
- BCM4500 register dump rendered as hex view
</TabItem>
</Tabs>
<Aside type="danger">
EEPROM flash is the only operation that can brick the device. The safety state machine prevents accidental writes, but a power loss during write will corrupt the boot image. The verify step detects partial writes — if it fails, **do not power cycle** until the flash is retried successfully.
</Aside>
### Stream <Badge text="F7" variant="note" />
Live MPEG-2 Transport Stream capture and analysis. Reads raw 188-byte TS packets from the SkyWalker-1 bulk endpoint, parses them in real time, and displays PID distribution statistics alongside a hierarchical PSI program structure tree.
![Stream analysis](../../../assets/tui/stream.svg)
- PID distribution table with count, percentage, CC errors, and known PID names
- PAT/PMT tree display showing transport stream ID, program numbers, PMT PIDs, and elementary stream types (video, audio, data)
- Aggregate stats: total packets, bytes, unique PIDs, CC errors, duration
- Capture-to-file mode for saving raw `.ts` files to disk
- Auto-starts monitoring in demo mode
<Aside type="tip">
The stream monitor batches UI updates at 500ms intervals to keep the interface responsive even at high packet rates. The USB bulk endpoint is always safely disarmed when monitoring stops.
</Aside>
### Config <Badge text="F8" variant="note" />
LNB power control, DiSEqC switching, and modulation/FEC configuration — all the hardware settings in one place.
![Hardware configuration](../../../assets/tui/config.svg)
<Tabs>
<TabItem label="LNB Control">
- Power On / Off toggle
- Voltage selection: 13V (vertical) / 18V (horizontal), with optional +1V boost
- 22 kHz tone toggle for high-band LNB switching
- Current draw warning (450 mA continuous max)
</TabItem>
<TabItem label="DiSEqC Switch">
- Port selector (14) sending committed commands
- Tone burst A/B for legacy switches
- Raw hex message input (36 byte DiSEqC 1.0/1.2 commands) with validation
</TabItem>
<TabItem label="Modulation / FEC">
- Modulation type dropdown: QPSK, Turbo QPSK, Turbo 8PSK, DCII Combo, DCII Split I/Q, DCII Offset QPSK, DSS
- FEC rate dropdown filtered per modulation group
- Symbol rate (256 Ksps 30 Msps) and frequency inputs
- Tune button applies settings to the BCM4500 demodulator
</TabItem>
</Tabs>
---
## Easter Eggs
@ -171,8 +252,10 @@ Use `--no-splash` to skip it.
## See Also
- [SkyWalker RF Tool](/tools/skywalker/) — CLI version of the same 5 modes (text-only output, scriptable)
- [SkyWalker RF Tool](/tools/skywalker/) — CLI version of the RF modes (text-only output, scriptable)
- [Spectrum Analysis](/tools/spectrum-analysis/) — practical how-to guides for each operating mode
- [Signal Monitoring](/bcm4500/signal-monitoring/) — SIGNAL_MONITOR register protocol and data format
- [Tuning Tool](/tools/tuning/) — primary tuning, LNB control, and transport stream capture
- [EEPROM Utilities](/tools/eeprom-utilities/) — standalone CLI for firmware updates (same safety protocol as F6 Device screen)
- [TS Stream Analyzer](/tools/ts-analyzer/) — standalone TS packet analyzer (same engine as F7 Stream screen)
- [RF Coverage](/hardware/rf-coverage/) — frequency coverage and antenna considerations

View File

@ -5,7 +5,7 @@ Uses Textual's headless run_test() + Pilot API to programmatically navigate
each screen and export SVG renders. Requires no hardware runs entirely
with DemoDevice synthetic signal data.
Output: ../site/src/assets/tui/*.svg (8 screenshots)
Output: ../site/src/assets/tui/*.svg (11 screenshots)
Usage:
cd tui && uv run python scripts/generate_screenshots.py
@ -46,7 +46,7 @@ def _save(svg: str, name: str) -> None:
async def capture_mode_screens() -> None:
"""Capture F1-F5 mode screens."""
"""Capture F1-F5 RF mode screens."""
app = _new_app(show_splash=False)
async with app.run_test(size=TERM_SIZE, headless=True) as pilot:
@ -67,6 +67,61 @@ async def capture_mode_screens() -> None:
_save(svg, filename)
async def capture_device_screen() -> None:
"""Capture F6 Device screen — show EEPROM tab with hex dump."""
app = _new_app(show_splash=False)
async with app.run_test(size=TERM_SIZE, headless=True) as pilot:
await pilot.pause(MOUNT_PAUSE)
# Switch to Device screen
await pilot.press("f6")
await pilot.pause(MODE_SWITCH_PAUSE)
# Wait for identity info to populate
await pilot.pause(1.0)
# Capture Firmware tab (default)
svg = app.export_screenshot(title="SkyWalker-1 — Device")
_save(svg, "device")
async def capture_stream_screen() -> None:
"""Capture F7 Stream screen — needs time for TS packets to accumulate."""
app = _new_app(show_splash=False)
async with app.run_test(size=TERM_SIZE, headless=True) as pilot:
await pilot.pause(MOUNT_PAUSE)
# Switch to Stream screen (auto-starts in demo mode)
await pilot.press("f7")
await pilot.pause(MODE_SWITCH_PAUSE)
# Wait for PID stats and PSI tree to populate
await pilot.pause(2.0)
svg = app.export_screenshot(title="SkyWalker-1 — Stream")
_save(svg, "stream")
async def capture_config_screen() -> None:
"""Capture F8 Config screen."""
app = _new_app(show_splash=False)
async with app.run_test(size=TERM_SIZE, headless=True) as pilot:
await pilot.pause(MOUNT_PAUSE)
# Switch to Config screen
await pilot.press("f8")
await pilot.pause(MODE_SWITCH_PAUSE)
# Wait for config status to load
await pilot.pause(0.5)
svg = app.export_screenshot(title="SkyWalker-1 — Config")
_save(svg, "config")
async def capture_dark_mode() -> None:
"""Capture dark-mode toggle with Star Wars notification toast."""
app = _new_app(show_splash=False)
@ -124,6 +179,9 @@ async def main() -> None:
captures = [
("Mode screens (F1-F5)", capture_mode_screens),
("Device screen (F6)", capture_device_screen),
("Stream screen (F7)", capture_stream_screen),
("Config screen (F8)", capture_config_screen),
("Dark mode toggle", capture_dark_mode),
("Splash screen", capture_splash),
("Star Wars easter egg", capture_starwars),