[docs](trx-rs): replace all ASCII diagrams with Mermaid

Convert ASCII art and box-drawing diagrams to Mermaid fenced code blocks
across README.md, CLAUDE.md, Architecture.md, Wxsat-Map-Overlay.md, and
trx-wxsat/README.md. Add Mermaid-only policy to CLAUDE.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-29 12:29:12 +02:00
parent a0f7de6af3
commit 83c23401fc
5 changed files with 63 additions and 81 deletions
+12 -8
View File
@@ -71,14 +71,14 @@ The project is split into a **server** (connects to the radio hardware) and a **
### Data flow ### Data flow
``` ```mermaid
Radio hardware graph TD
↕ serial/TCP Radio["Radio Hardware"] <-->|serial / TCP| Server["trx-server (rig_task.rs)"]
trx-server (rig_task.rs) Server <-->|"JSON-TCP :4530"| Client["trx-client (remote_client.rs)"]
↕ trx-protocol JSON-TCP (port 4530) Server -->|"Opus-TCP :4531"| Client
trx-client (remote_client.rs) Client <-->|internal channels| F1["HTTP Frontend :8080"]
internal channels Client <-->|internal channels| F2["rigctl Frontend :4532"]
Frontends: HTTP (8080), rigctl (4532), http-json (ephemeral) Client <-->|internal channels| F3["JSON-TCP Frontend"]
``` ```
### trx-core controller ### trx-core controller
@@ -94,6 +94,10 @@ The rig controller (`src/trx-core/src/rig/controller/`) is the central state man
Signal decoders run as background tasks in `trx-server`, consuming decoded audio. `trx-ftx` provides the FT8/FT4/FT2 decoder in pure Rust. Decoded frames can be forwarded to PSKReporter and APRS-IS (IGate) uplinks, or logged via `trx-decode-log`. Signal decoders run as background tasks in `trx-server`, consuming decoded audio. `trx-ftx` provides the FT8/FT4/FT2 decoder in pure Rust. Decoded frames can be forwarded to PSKReporter and APRS-IS (IGate) uplinks, or logged via `trx-decode-log`.
## Diagrams
Always use [Mermaid](https://mermaid.js.org/) for diagrams in Markdown files. Never use ASCII art, box-drawing characters, or plain-text diagrams. GitHub renders Mermaid natively in ```mermaid fenced code blocks.
## Commit Format ## Commit Format
``` ```
+8 -8
View File
@@ -82,14 +82,14 @@ Build without SDR support: `cargo build --release --no-default-features`
## How It Works ## How It Works
``` ```mermaid
Radio / SDR hardware graph TD
| serial or USB Radio["Radio / SDR Hardware"] <-->|"serial or USB"| Server["trx-server<br/>rig control, DSP, decoders, audio capture"]
trx-server rig control, DSP, decoders, audio capture Server <-->|"JSON-TCP :4530"| Client["trx-client<br/>remote connection, audio relay"]
| JSON-TCP (4530) + Opus-TCP (4531) Server -->|"Opus-TCP :4531"| Client
trx-client remote connection, audio relay Client <-->|internal channels| F1["Web UI :8080"]
| Client <-->|internal channels| F2["rigctl :4532"]
Frontends Web UI (8080), rigctl (4532), JSON-TCP Client <-->|internal channels| F3["JSON-TCP"]
``` ```
`trx-server` owns hardware access and runs the DSP pipeline. `trx-server` owns hardware access and runs the DSP pipeline.
+22 -30
View File
@@ -58,36 +58,28 @@ Target users are amateur radio operators who want networked, automated, or multi
## High-Level Architecture ## High-Level Architecture
``` ```mermaid
┌──────────────────────────────────────────────────────────┐ graph TD
│ trx-server │ subgraph server["trx-server"]
│ │ HW["Radio Hardware"] <-->|"CAT protocol<br/>serial / TCP"| Backend["Rig Backend<br/>(ft817 / ft450d / sdr)"]
│ Radio Hardware (serial/TCP) │ Backend --> RigTask["rig_task.rs<br/>(state machine)"]
│ ↕ CAT protocol │ RigTask --> Listener["listener.rs<br/>(JSON TCP :4530)"]
│ Rig Backend ──────── rig_task.rs ─── listener.rs │ RigTask --> Audio["audio.rs<br/>(Opus :4531)"]
│ (ft817/ft450d/sdr) (state machine) (JSON TCP :4530) │ Audio --> Decoders["Decoders<br/>(APRS, CW, FT8, WSPR, RDS)"]
│ │ │ Decoders --> Uplinks["PSKReporter / APRS-IS"]
│ audio.rs │ end
│ (Opus :4531) │
│ │ │ subgraph client["trx-client"]
│ Decoders │ Remote["remote_client.rs<br/>(polls state, routes commands)"]
│ (APRS, CW, FT8, WSPR, RDS) │ Remote <-->|"mpsc / watch channels"| HTTP["trx-frontend-http<br/>(Web UI :8080)"]
│ PSKReporter / APRS-IS │ Remote <-->|"mpsc / watch channels"| Rigctl["trx-frontend-rigctl<br/>(rigctl :4532)"]
└──────────────────────────────────────────────────────────┘ Remote <-->|"mpsc / watch channels"| JSON["trx-frontend-http-json<br/>(JSON/TCP)"]
↕ JSON TCP (port 4530) end
↕ Opus audio TCP (port 4531)
┌──────────────────────────────────────────────────────────┐ Listener <-->|"JSON TCP :4530"| Remote
│ trx-client │ Audio -->|"Opus TCP :4531"| Remote
│ │
│ remote_client.rs (polls state, routes commands) │ HTTP & Rigctl & JSON <--> Users["End Users<br/>(Browser / Hamlib / Custom tools)"]
│ ↕ internal mpsc/watch channels │
│ Frontends: │
│ trx-frontend-http (Web UI :8080) │
│ trx-frontend-rigctl (rigctl :4532) │
│ trx-frontend-http-json (JSON/TCP ephemeral) │
└──────────────────────────────────────────────────────────┘
↕ Browser / Hamlib / Custom tools
End Users
``` ```
The server and client are separate binaries. They communicate over **JSON-over-TCP** (control) and **Opus-encoded TCP** (audio). Both binaries can load shared-library plugins at startup. The server and client are separate binaries. They communicate over **JSON-over-TCP** (control) and **Opus-encoded TCP** (audio). Both binaries can load shared-library plugins at startup.
+10 -10
View File
@@ -27,16 +27,16 @@ can be projected as semi-transparent overlays on the same Leaflet map.
### Data flow ### Data flow
``` ```mermaid
Pass decoded (APT / LRPT) graph TD
finalize_wxsat_pass / finalize_lrpt_pass (trx-server/audio.rs) A["Pass decoded (APT / LRPT)"] --> B["finalize_wxsat_pass / finalize_lrpt_pass<br/>(trx-server/audio.rs)"]
SGP4 propagation using satellite TLE + pass timestamps B --> C["SGP4 propagation using satellite TLE + pass timestamps"]
Compute geo_bounds [[south, west], [north, east]] C --> D["Compute geo_bounds<br/>[[south, west], [north, east]]"]
Compute ground_track [[lat, lon], ...] D --> E["Compute ground_track<br/>[[lat, lon], ...]"]
Attach to WxsatImage / LrptImage E --> F["Attach to WxsatImage / LrptImage"]
Broadcast via DecodedMessage F --> G["Broadcast via DecodedMessage"]
SSE → browser G --> H["SSE → browser"]
wxsat.js: L.imageOverlay() + L.polyline() on aprsMap H --> I["wxsat.js: L.imageOverlay() + L.polyline() on aprsMap"]
``` ```
### Geo-referencing strategy ### Geo-referencing strategy
+11 -25
View File
@@ -34,17 +34,11 @@ trx-wxsat/src/
### NOAA APT ### NOAA APT
``` ```mermaid
FM-demodulated audio (any sample rate) graph TD
AptDemod: FFT Hilbert transform, bandpass @ 2400 Hz ±1040 Hz A["FM-demodulated audio<br/>(any sample rate)"] -->|"AptDemod: FFT Hilbert transform,<br/>bandpass @ 2400 Hz ±1040 Hz"| B["AM envelope<br/>resampled to 4160 Hz"]
B -->|"SyncTracker: 1040 Hz<br/>sync-A marker correlation"| C["Aligned 2080-sample lines<br/>[SyncA 39][SpaceA 47][ImageA 909][TelA 45]<br/>[SyncB 39][SpaceB 47][ImageB 909][TelB 45]"]
AM envelope resampled to 4160 Hz C -->|"Telemetry extraction,<br/>wedge-based radiometric calibration,<br/>histogram EQ"| D["PNG image<br/>(1818 x N pixels, dual-channel side-by-side)"]
│ SyncTracker: 1040 Hz sync-A marker correlation
Aligned 2080-sample lines → [SyncA 39][SpaceA 47][ImageA 909][TelA 45][SyncB 39][SpaceB 47][ImageB 909][TelB 45]
│ Telemetry extraction, wedge-based radiometric calibration, histogram EQ
PNG image (1818 × N pixels, dual-channel side-by-side)
``` ```
**Key DSP details:** **Key DSP details:**
@@ -62,20 +56,12 @@ PNG image (1818 × N pixels, dual-channel side-by-side)
### Meteor-M LRPT ### Meteor-M LRPT
``` ```mermaid
Baseband samples (any sample rate) graph TD
QpskDemod: Costas loop carrier recovery + Gardner TED symbol timing A["Baseband samples<br/>(any sample rate)"] -->|"QpskDemod: Costas loop carrier recovery<br/>+ Gardner TED symbol timing"| B["Soft symbols (±1.0, I/Q interleaved)<br/>@ 72 ksym/s"]
B -->|"CaduFramer: hard-decision,<br/>ASM (0x1ACFFC1D) search, frame lock"| C["1024-byte CADUs<br/>(CCSDS transfer frames)"]
Soft symbols (±1.0, I/Q interleaved) @ 72 ksym/s C -->|"ChannelAssembler:<br/>VCID → APID routing, MCU extraction"| D["Per-APID pixel rows<br/>(1568 px wide)"]
│ CaduFramer: hard-decision, ASM (0x1ACFFC1D) search, frame lock D -->|"RGB composite (APIDs 64/65/66)<br/>or grayscale fallback"| E["PNG image<br/>(1568 x N pixels)"]
1024-byte CADUs (CCSDS transfer frames)
│ ChannelAssembler: VCID → APID routing, MCU extraction
Per-APID pixel rows (1568 px wide)
│ RGB composite (APIDs 64/65/66) or grayscale fallback
PNG image (1568 × N pixels)
``` ```
**LRPT channel mapping:** **LRPT channel mapping:**