From 04d965d67a7264a1c7c211494aebda1953df7603 Mon Sep 17 00:00:00 2001 From: "info@mode42.com" Date: Fri, 7 Aug 2026 18:25:13 +0000 Subject: Initial push --- docs/DEV/TNC-MODEM-DEV.md | 191 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 docs/DEV/TNC-MODEM-DEV.md (limited to 'docs/DEV/TNC-MODEM-DEV.md') diff --git a/docs/DEV/TNC-MODEM-DEV.md b/docs/DEV/TNC-MODEM-DEV.md new file mode 100644 index 0000000..e547d0f --- /dev/null +++ b/docs/DEV/TNC-MODEM-DEV.md @@ -0,0 +1,191 @@ +# TNC / Modem bring-up · MAX25-Stack + +English bring-up for **TNCs** (HDLC + KISS on host serial) and **BayCom/based** modems (bits↔AFSK + PTT; host owns HDLC). Applies to MAX25-Stack and to any stack that attaches the same hardware classes. + +--- + +## 1. Roles — TNC vs modem + +| Class | What it is | Host owns | Typical face | +|-------|------------|-----------|--------------| +| **TNC** (TNC2C, PK-TNC2, TNC2multi, …) | Firmware does HDLC; host talks **command mode** then **KISS** on UART | Serial lifecycle, recovery, KISS entry | `tnc2c`, `pktnc2`, … | +| **BayCom/based** modem | Board is **modem-only** (TCM3105-class AFSK + PTT) | HDLC, SER12 bit clock, KISS PTY, PTT | **`max25e0`** (bcpr) | +| Soft-modem (CRDOP) | Soundcard AFSK | Audio + soft HDLC | `soft-crdop` | + +```text +TNC path: Radio AF ↔ TNC (HDLC+modem) ↔ UART KISS ↔ host stack +Modem path: Radio AF ↔ BayCom/based chip ↔ SER12 UART ↔ host HDLC (bcpr) ↔ KISS +``` + +Do **not** treat a BayCom/based board as a TNC. Do **not** open the same `/dev/tty*` from two processes. + +--- + +## 2. KISS bring-up (any stack) + +### 2.1 Serial ownership + +| Rule | Why | +|------|-----| +| **One opener** per UART | Dual openers → garbled RX, failed recovery, flaky KISS | +| Hold **DTR+RTS high** while the port is owned | Landolt TNC2C terminal detect needs DTR high at power-on; drop on close → echo-only | +| Match **baud / line** to hardware | Wrong baud → garbage or echo only | + +| Device class (typical) | Baud | Line | Notes | +|------------------------|------|------|-------| +| Landolt TNC2C | **19200** | 8N1 | Not 4800/9600/7E1 | +| PK-TNC2 / many TF boards | **9600** | 8N1 | Profile-dependent | +| BayCom/based SER12 | UART clocked by host SER12 | — | Product path: **max25-bcpr**, not kernel `baycom_ser_fdx` | + +### 2.2 Command sequence (TheFirmware / TNC-2 class) + +| Step | Action | +|------|--------| +| 1 | Free the port (`pkill` stray terminals; one stack owns the fd) | +| 2 | Open UART with DTR+RTS high; settle ~2 s | +| 3 | Reach **terminal / host command mode** (banner / `cmd:`) — see recovery below | +| 4 | Set callsign / radio params as required by firmware | +| 5 | Enter KISS: TheFirmware **ESC `@K`** (`0x1B 40 4B`); legacy TAPR `kiss on` only as fallback | +| 6 | Keep the **same process** owning the port for KISS DATA | + +KISS exit (if needed): `kiss off`, or frame `0xC0 0xFF 0xC0`, or firmware `RESTART`. + +### 2.3 Boot-wait (cold start) + +After mains loss or cold power without DTR, some boards (notably Landolt TNC2C) need **boot-wait with DTR high during power-on**: + +```bash +cd stacks/tncs +./tnc2c-boot-wait.sh /dev/ttyS4 # keep script open; power OFF 10s → ON +# then start the stack immediately so DTR stays high +``` + +Quiet AF / closed squelch (CD off) during boot improves banner reliability. + +--- + +## 3. Power-cycle history — and the correct path + +| Era | Practice | Status | +|-----|----------|--------| +| Former | Power-cycle + boot-wait for almost every KISS/host recovery | Still valid as **rescue** | +| Root cause (hardware) | Landolt: DTR must be high **at** power-on; late open → echo/transparent | Not fully soft-fixable | +| Root cause (host) | Recovery answers lost if an RX thread races the drain; no escalation to boot-wait | Fixed / mitigated in product recovery path | +| Correct default | **Software recovery ladder first**; power-cycle only if echo-only after ladder | Prefer `tnc_serial_recovery` / `tnc2c-host-reset` | + +### Software-first ladder (summary) + +1. DTR+RTS high, passive listen +2. KISS return `0xC0 0xFF 0xC0` +3. JHOST 0 flush (`^Q^X` + nulls + `JHOST 0`) +4. ESC `V` / ESC `QRES` (software cold boot; DTR stays high) +5. Legacy `kiss off` + `INFO` (last resort) +6. KISS entry ESC `@K` + +Success markers: `TheFirmware`, `NORD`, `Version 2.7`, `Checksum`, `cmd:`. + +| If… | Then… | +|-----|--------| +| Ladder fails → echo only | `./tnc2c-boot-wait.sh` + power OFF→ON with DTR held | +| Standalone reset OK, stack FAIL | Check dual openers / RX race / start order | +| After boot-wait | Start stack **immediately** (avoid DTR drop gap) | + +Detail: `stacks/tncs/docs/TNC-RECOVERY.md`. + +--- + +## 4. Common failure modes + +| Symptom | Likely cause | Fix | +|---------|--------------|-----| +| Garbage / no banner | Wrong baud or 7E1 | Match profile (e.g. TNC2C **19200 8N1**) | +| Echo only (`INFO`→`INFO`) | No terminal mode; DTR missed at power-on | Recovery ladder → else boot-wait + power-cycle | +| Binary noise, no commands | Stuck in KISS | KISS return frame or `kiss off` | +| Intermittent recovery | Second process on same tty | One owner; kill minicom/`fuser` | +| Silent TX after good session (modem) | **Stale KISS PTY** (max25-bcprd recycled outside max25d) | Restart **max25d only** (`auto_start` owns max25-bcprd) | +| TX blocked with Soft-DCD busy | `fulldup=no` + Soft-DCD holds channel | Bench: `fulldup=yes`; production CSMA prove-out later | +| Closed squelch ≠ TX fail | No RX noise does not prove PTT failure | Separate MCR/keying from mic wiring | + +--- + +## 5. MAX25-Stack + +### 5.1 Paths + +| Path | Role | +|------|------| +| **TNC** | `stacks/tncs/` · devices `tnc2c` / `pktnc2` / … · KISS-serial backend | +| **BayCom/based** | `stacks/max25-bcpr/` · `[features] max25_bcpr=yes` · device **`max25e0`** | +| **CRDOP** | `stacks/crdop/` · soft-modem (out of scope here beyond role table) | + +### 5.2 Device face `max25e0` + +| Surface | Name | +|---------|------| +| Product device id | **`max25e0`** | +| INI mapping | `max25e0 = max25-bcpr:bc0` (right side = **backend:port tag**, not product id) | +| Multi-dev | Always forks **`max25e0:bcN`** | +| Forbidden ids | `bcpr`, `bcpr-bc0`, `bcpr-bc1`, any `bcpr-*` as product face | +| `max25e*` family | **MAX25-Stack only** | + +### 5.3 Start + +```bash +# Feature (site or ./local — never commit live secrets) +# [features] +# max25_bcpr = yes +# +# [devices] +# max25e0 = max25-bcpr:bc0 + +./scripts/run-max25d.sh # escalates root only when ttyS/USB/SER12 needs it +./scripts/run-max25-terminal.sh -U /run/max25/modem.sock +``` + +| Rule | Value | +|------|-------| +| Preferred ownership | **max25d** starts/stops max25-bcprd (`auto_start`) | +| Do not | Recycle `max25-bcprd` under a live max25d (stale PTY) | +| Root | **Only when necessary** (SER12 / ioperm / `/dev/port` / ttyS bind) — TCP/unix-only may stay unprivileged | +| Drop | After privileged init, drop to `[daemon] user=` / `group=` when set | + +Site INI examples: `/etc/max25/max25d.ini`, `/etc/max25/max25-bcpr.ini`. Tree secrets: `./local/`. + +### 5.4 RX before TX (live RF) + +Prove **RX** before live **`--tx`** / on-air SEND: + +| Class | RX proof | +|-------|----------| +| BayCom/based | Soft-DCD / noise activity or decoded KISS RX | +| TNC | CONNECT + STATUS (RX ready) before SEND | +| Offline L0 | Encode/decode without PTT — allowed | + +`--force-tx` is debug-only. See [TX-RX-TEST.md](docs/TX-RX-TEST.md). + +### 5.5 Minimal matrices (no duplication) + +| Goal | Doc | +|------|-----| +| Day-to-day ops | [MAX25-OPERATOR-RUNBOOK.md](docs/MAX25-OPERATOR-RUNBOOK.md) | +| BayCom/based / bcpr | [BAYCOM.md](docs/BAYCOM.md) · [BAYCOM-FREEZES.md](docs/BAYCOM-FREEZES.md) | +| Linear operator guide | [MASTER-GUIDE.md](docs/MASTER-GUIDE.md) | +| TNC software recovery | [stacks/tncs/docs/TNC-RECOVERY.md](stacks/tncs/docs/TNC-RECOVERY.md) | +| Device model | [PLUGINS-DEVICE-MODEL.md](docs/PLUGINS-DEVICE-MODEL.md) | +| Doc index | [docs/README.md](docs/README.md) | + +--- + +## 6. Quick decision tree + +```text +Need KISS on a UART TNC? +├─ Port free + correct baud? +│ └─ no → fix ownership / baud +├─ Terminal / cmd: present? +│ ├─ no → software recovery ladder +│ │ └─ still echo only → boot-wait + power-cycle (DTR high) +│ └─ yes → ESC @K (or profile kiss entry) → keep one owner +└─ BayCom/based? + └─ [features] max25_bcpr=yes · max25e0 · run-max25d.sh · RX proof → then TX +``` -- cgit v1.3.1