[feat](trx-wefax): implement WEFAX decoder with full server and frontend integration
Pure Rust WEFAX (Weather Facsimile) decoder supporting 60/90/120/240 LPM, IOC 288 and 576, with automatic APT tone detection and phase alignment. Core DSP pipeline: - Polyphase rational resampler (48k→11025 Hz) - FM discriminator (Hilbert FIR + instantaneous frequency) - Goertzel tone detector (300/450/675 Hz APT tones) - Phase alignment via cross-correlation on phasing signal - Line slicer with linear interpolation pixel clock recovery - Image assembler with PNG encoding State machine: Idle→StartDetected→Phasing→Receiving→Stopping Server integration: - WefaxMessage/WefaxProgress in trx-core DecodedMessage - DecoderConfig, DecoderResetSeqs, RigCommand wefax variants - DECODER_REGISTRY entry in trx-protocol - DecoderHistories/DecoderLoggers wefax support - run_wefax_decoder() async task in trx-server audio.rs - History persistence in pickledb store Frontend integration: - wefax.js plugin with live canvas rendering and gallery - HTML sub-tab with canvas, gallery, toggle/clear controls - SSE dispatch for wefax/wefax_progress events - Decode history worker and restore support - Toggle/clear API endpoints 19 unit tests covering resampler, FM discriminator, tone detection, phasing, line slicing, image encoding, and decoder state machine. https://claude.ai/code/session_019eyxgx3LuhcFZ7T5tr2Trm Signed-off-by: Claude <noreply@anthropic.com>
This commit is contained in:
+24
-24
@@ -1,7 +1,7 @@
|
||||
# WEFAX / Radiofax Decoder Implementation Plan
|
||||
|
||||
> **Crate**: `trx-wefax` — `src/decoders/trx-wefax/`
|
||||
> **Status**: Draft — 2026-04-02
|
||||
> **Status**: Implemented (Phases 1–3b) — 2026-04-02
|
||||
|
||||
## 1. Overview
|
||||
|
||||
@@ -741,53 +741,53 @@ const HISTORY_GROUP_KEYS = [
|
||||
|
||||
## 8. Implementation Phases
|
||||
|
||||
### Phase 1: Core DSP (MVP)
|
||||
### Phase 1: Core DSP (MVP) ✅
|
||||
|
||||
1. **Resampler** — 48k→11025 polyphase resampler with tests.
|
||||
2. **FM discriminator** — Hilbert FIR + instantaneous freq, verify
|
||||
1. ✅ **Resampler** — 48k→11025 polyphase resampler with tests.
|
||||
2. ✅ **FM discriminator** — Hilbert FIR + instantaneous freq, verify
|
||||
against synthetic 1500–2300 Hz sweeps.
|
||||
3. **Tone detector** — Goertzel at 300/450/675 Hz with debounce.
|
||||
4. **Line slicer** — Fixed-config (manual LPM+IOC) line extraction.
|
||||
5. **Image buffer + PNG** — Greyscale line accumulation, `image` or
|
||||
`png` crate for encoding.
|
||||
3. ✅ **Tone detector** — Goertzel at 300/450/675 Hz with debounce.
|
||||
4. ✅ **Line slicer** — Fixed-config (manual LPM+IOC) line extraction.
|
||||
5. ✅ **Image buffer + PNG** — Greyscale line accumulation, `png`
|
||||
crate for encoding.
|
||||
|
||||
Deliverable: decode a known WEFAX WAV recording at a single speed/IOC.
|
||||
|
||||
### Phase 2: Automatic Detection
|
||||
### Phase 2: Automatic Detection ✅
|
||||
|
||||
6. **State machine** — Full `Idle→StartDetected→Phasing→Receiving→Stopping`
|
||||
6. ✅ **State machine** — Full `Idle→StartDetected→Phasing→Receiving→Stopping`
|
||||
transitions driven by tone detector.
|
||||
7. **Phase alignment** — Cross-correlation phasing detector.
|
||||
8. **Auto IOC/LPM** — IOC from start tone frequency; LPM from phasing
|
||||
7. ✅ **Phase alignment** — Cross-correlation phasing detector.
|
||||
8. ✅ **Auto IOC/LPM** — IOC from start tone frequency; LPM from phasing
|
||||
line duration measurement.
|
||||
|
||||
Deliverable: fully automatic reception of a single image without manual config.
|
||||
|
||||
### Phase 3: Server Integration
|
||||
### Phase 3: Server Integration ✅
|
||||
|
||||
9. **`trx-core` message types** — `WefaxMessage`, `WefaxProgress` in
|
||||
9. ✅ **`trx-core` message types** — `WefaxMessage`, `WefaxProgress` in
|
||||
`DecodedMessage`.
|
||||
10. **`trx-server` task** — `run_wefax_decoder()`, history, logging.
|
||||
11. **Protocol registry** — `DECODER_REGISTRY` entry for `"wefax"`.
|
||||
10. ✅ **`trx-server` task** — `run_wefax_decoder()`, history, logging.
|
||||
11. ✅ **Protocol registry** — `DECODER_REGISTRY` entry for `"wefax"`.
|
||||
|
||||
Deliverable: backend wefax decoding with SSE event broadcast.
|
||||
|
||||
### Phase 3b: Frontend Wiring
|
||||
### Phase 3b: Frontend Wiring ✅
|
||||
|
||||
12. **Rust asset pipeline** — `status.rs` embed, `assets.rs` gzip
|
||||
12. ✅ **Rust asset pipeline** — `status.rs` embed, `assets.rs` gzip
|
||||
cache + route, `decoder.rs` toggle/clear endpoints, `api/mod.rs`
|
||||
registration (§7.5.1).
|
||||
13. **HTML scaffold** — sub-tab button, sub-tab panel with canvas +
|
||||
13. ✅ **HTML scaffold** — sub-tab button, sub-tab panel with canvas +
|
||||
gallery, overview entry, about row (§7.5.2).
|
||||
14. **Plugin loading** — add `/wefax.js` to `pluginScripts`
|
||||
14. ✅ **Plugin loading** — add `/wefax.js` to `pluginScripts`
|
||||
`'digital-modes'` array (§7.5.3).
|
||||
15. **SSE dispatch** — `wefax` / `wefax_progress` handlers in
|
||||
15. ✅ **SSE dispatch** — `wefax` / `wefax_progress` handlers in
|
||||
`app.js` decode event dispatcher (§7.5.4).
|
||||
16. **`wefax.js` plugin** — live canvas rendering, gallery
|
||||
16. ✅ **`wefax.js` plugin** — live canvas rendering, gallery
|
||||
thumbnails, history restore, toggle/clear wiring (§7.5.5).
|
||||
17. **Image serving** — `/images/{filename}` static route for
|
||||
completed PNGs (§7.5.7).
|
||||
18. **History worker** — add `"wefax"` to `HISTORY_GROUP_KEYS`
|
||||
completed PNGs (§7.5.7). *(deferred: images served from output_dir)*
|
||||
18. ✅ **History worker** — add `"wefax"` to `HISTORY_GROUP_KEYS`
|
||||
(§7.5.8).
|
||||
|
||||
Deliverable: end-to-end live WEFAX decoding with in-browser image preview.
|
||||
|
||||
Reference in New Issue
Block a user