radio_utils_emu/lib.rs
1//! OpenHPSDR Protocol-1 hardware emulator.
2//!
3//! Speaks the Hermes / Hermes Lite 2 wire format end-to-end over UDP, so
4//! the rest of the workspace (and third-party clients like Thetis,
5//! deskHPSDR, the web client) can be developed and tested without real
6//! hardware. The CLI binary lives in `src/main.rs` —
7//! `cargo run --release -p radio-utils-emu -- --radio hermeslite --echo-live`
8//! is the standard "virtual band" launch.
9//!
10//! # Echo modes
11//!
12//! [`radio::EchoMode`] selects how the emulator handles transmitted IQ:
13//!
14//! * `Live` — the bounded per-frequency `LiveBuffer` mixes concurrent TXers
15//! additively at a real-time write head (`feed_from(client_id, samples)`)
16//! and plays back to listeners with a ~21 ms delay (`LIVE_DELAY` in
17//! `radio.rs`). Two operators keying simultaneously on the same frequency
18//! superimpose like real co-channel signals (QRM); the buffer fills at
19//! 1× real-time regardless of how many TXers are active. This is the
20//! mode used by hosted multi-user "virtual band" deployments.
21//!
22//! * `Loop` — TX is recorded into the per-frequency `FreqRecorder`, trimmed
23//! of leading/trailing silence on commit, padded with
24//! `LOOP_TAIL_SILENCE_SEC` (currently 500 ms) of silence so each iteration
25//! is audibly separated, then loops forever with a 40 ms head/tail
26//! crossfade. The recording **persists across PTT cycles** within a
27//! `LOOP_SESSION_GAP` window (currently 30 s): a slow CW operator who
28//! keys "C", pauses, then keys "Q" gets both letters with the actual
29//! inter-cycle silence preserved in the loop, instead of the second
30//! cycle overwriting the first.
31//!
32//! * `None` — no echo; RX delivers signal-generator noise only.
33//!
34//! # Multi-client model
35//!
36//! Each Protocol-1 client connection (identified by `SocketAddr`) gets its
37//! own `client_task` running an `tokio::time::interval` at the wire packet
38//! cadence (1024 Hz typical). The `MAX_CLIENTS` cap is configurable via
39//! [`protocol1::DEFAULT_MAX_CLIENTS`] (32) and can be overridden per process
40//! through the binary's `--max-clients` flag.
41//!
42//! Live-mode TX from N clients on one freq mixes additively: each call to
43//! [`radio::EchoBuffer::feed`] dispatches to `LiveBuffer::feed_from` which
44//! writes additively at the client's tracked offset. (The `client_id`
45//! parameter on `feed` is only consulted in live mode.) Loop mode falls
46//! back to a single shared append buffer per freq — fine for the typical
47//! single-operator-at-a-time use case; concurrent loop-mode TX is not
48//! mixed correctly.
49
50pub mod protocol1;
51pub mod radio;