diff options
Diffstat (limited to 'stacks/crdop/docs/HOST-PROTOCOL-SPEC.md')
| -rw-r--r-- | stacks/crdop/docs/HOST-PROTOCOL-SPEC.md | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/stacks/crdop/docs/HOST-PROTOCOL-SPEC.md b/stacks/crdop/docs/HOST-PROTOCOL-SPEC.md new file mode 100644 index 0000000..d45c7e5 --- /dev/null +++ b/stacks/crdop/docs/HOST-PROTOCOL-SPEC.md @@ -0,0 +1,103 @@ +# M25 SoftModem host protocol — implementation spec (frozen for v1.0.0) + +**CRDOP** = **MAX25-SoftModem** · Native host wire for MAX25-SoftModem · **Not** ARDOP FEC/ARQ. + +**Normative code:** `stacks/crdop/lib/m25_host_protocol.py` · **Consumer:** `max25d` `CrdopTcpBackend`, `audio-dummyd`, `crdopc` launcher. + +--- + +## Transport + +| Channel | Default port | Wire | +|---------|--------------|------| +| **Control** | **8515** | Line-oriented ASCII, **`\n`** terminated (native) | +| **Data** | **8516** (= ctrl + 1) | Binary AX.25 UI body **without** HDLC flags or FCS | + +| Mode | Control terminator | Data semantics | +|------|-------------------|----------------| +| **Native M25/KISS** | `\n` | KISS DATA equivalent — 16+ byte UI body | + +### Bench alternate ports + +When `soft-crdop` and `audio-dummyd` run on one host, bench daemon may use **8520/8521** via CLI. Production `crdopc` and INI default **8515/8516**. + +--- + +## Control commands (native) + +All commands are single lines. Reply is one line ending `\n`. + +| Command | Args | Reply | Behaviour | +|---------|------|-------|-----------| +| `INITIALIZE` | — | `OK` | Reset session state | +| `PROTOCOLMODE` | `KISS` | `OK` | Select KISS-semantics data channel | +| `MYCALL` | `CALL-SSID` | `OK` | Store station ID (uppercase) | +| `LISTEN` | `TRUE`/`FALSE` | `OK` | RX enable (default true) | +| `PING` | — | `OK` | Liveness | +| `STATUS` | — | `STATUS ready mycall=…` | State snapshot | +| *(unknown)* | — | `ERR unknown command` | | + +**Not supported on native path:** `PROTOCOLMODE FEC`, `FECMODE`, ARQ bandwidth commands — ARDOP is a separate optional plugin, not part of CRDOP. + +--- + +## Data channel + +### TX (host → modem) + +1. TCP connect to data port. +2. Send **one** AX.25 UI frame body: `dest(7) + src(7) + ctrl(1) + pid(1) + info(0..256)`. +3. Modem responds `OK` or `ERR …` (ASCII line). + +Modem builds on-air: HDLC flags, bit-stuffing, frequency-toggle line code, AFSK PHY — see `acoustic_engine.encode_ax25_ui()`. + +### RX (modem → host) + +Native bench: optional `STATUS` lines on control channel. Production: `max25d` parses demodulated UI and displays `[CRDOP AX25 UI src>dst] text`. + +--- + +## max25d integration + +```ini +[devices] +soft-crdop = crdop:default + +[device.soft-crdop] +host = 127.0.0.1 +port = 8515 +listen = yes +``` + +`CrdopTcpBackend` on `open()`: + +1. TCP connect `host:port` (ctrl), `host:port+1` (data). +2. Send `INITIALIZE`, `PROTOCOLMODE KISS`, `MYCALL …`, `LISTEN TRUE` (each `\n`). + +--- + +## Layer separation + +| Layer | On data TCP | On air | +|-------|-------------|--------| +| AX.25 UI body | ✅ | Inside HDLC | +| HDLC + CRC-16 | ❌ | ✅ | +| Bell 202 AFSK | ❌ | ✅ | + +Same rule as KISS `0x00` DATA frames in `kiss_bridge.py`. + +--- + +## Compliance tests + +| Test | Command | +|------|---------| +| Unit | `pytest stacks/daemon/test_crdop_backend.py` | +| Bench host | `python3 stacks/crdop/tools/audio-dummyd.py --ctrl-port 8515 --data-port 8516` | +| Loopback DSP | `pytest stacks/crdop/test_bell202_line_code.py` | + +--- + +## Version + +Frozen for **MAX25-Stack v1.0.0** (dev track `CUR999`). Changes require bump in this file + `PROTOCOL.md` + `test_crdop_backend.py`. |
