# Protocol

Two protocols connect the pieces of HIL-OS: a **serial wire protocol** between
the monitor and the firmware, and a **JSON IPC protocol** between the monitor
and headless clients (Node, `hil-cli simulate`, tests).

## Serial wire protocol

### Frame format

```
ACTION TYPE PIN VAL1 VAL2|CRC\r
```

* Fields are space-separated ASCII.
* `CRC` is the **XOR** of every byte in the command part, formatted as two
  uppercase hex digits (`%02X`).
* Frames end with `\r` (CR).
* Example: `W D 13 1 0|5D\r`

### Actions

| Letter | Meaning | Example |
|--------|---------|---------|
| `W` | Write | `W D 13 1 0` (digital high), `W A 9 128 0` (PWM), `W P 9 128 0` (PWM alias) |
| `R` | Read | `R D 2 0 0` (digital), `R A 0 0 0` (analog) |
| `T` | Tone | `T D 8 1000 200` (pin 8, 1 kHz, 200 ms) |
| `S` | Pulse | `S D 13 5 1000` (5 toggles, 1000 µs) |
| `E` | Digital event arm | `E D 2 3 0` (RISING) |
| `C` | Analog change arm | `C A 0 512 0` (threshold) |
| `I` | I2C | `I W 104 0 0` (write), `I R 104 1 0` (read) |
| `L` | LCD | `L I 39 0 0` (init), `L C 0 0 0` (clear), `L P 0 0 text` |
| `V` | Servo | `V S 9 90 0` |
| `M` | MP3 | `M P 10 1 0` (play), `M V 10 20 0` (volume) |
| `F` | SD card | `F W 10 line` |
| `H` | Sensor read | `H D pin 22 0` (DHT22), `H L pin 0 0` (LM35), `H U trig echo 0` |
| `N` | NeoPixel | `N S idx r g`, `N B idx b`, `N U pin leds 0` |
| `X` | Attention input | `X S pin weight 0` |
| `Z` | PID | `Z I ch in out`, `Z P ch kp ki`, `Z D ch kd 0`, `Z S ch sp 0` (closed loop), `Z O ch val 0` (open loop) |
| `Q` | Batch flush | `Q Q 0 0 0` |
| `A` | Autopilot | `A C 0 0 0` (clear), `A W <act> <typ> <pin>` (record), `A D <v1> <v2> 0` (record data), `A E 1 0 0` (commit), `A S 1 0 0` (boot-arm) |
| `D` | Delay (autopilot) | recorded via `A W 68 0 0` then `A D <ms> 0 0` |

### Replies

| Reply | Meaning |
|-------|---------|
| `ACK` | Command accepted (most commands) |
| `D:pin:val` | Digital read result (e.g. `D:2:1`) |
| `A:pin:val` | Analog read result (e.g. `A:0:512`) |
| `I:addr:val` | I2C read result |
| `(temp hum)` | DHT sensor tuple |
| `EVT:D:pin:val` | Digital event fired |
| `EVT_A:A:pin:val` | Analog change event fired |

### Batching

`BATCH-BEGIN` suppresses ACK waits so frames stream back-to-back;
`BATCH-END` flushes with `Q Q 0 0 0`.

### Autopilot delay encoding

`DELAY` in autopilot mode is recorded as `A W 68 0 0` (action `D`, ASCII 68)
followed by `A D <ms> 0 0`. The firmware's `runAutopilot` sleeps
`val1` milliseconds — this is how delays greater than 127 ms survive the
signed 8-bit pin field.

## JSON IPC protocol (headless)

The monitor is started with `-ipc [-port none]`. All output is JSON lines on
stdout; scripts are streamed on stdin, each terminated by a line containing
exactly `__HIL_END__`.

### Messages (monitor → client)

```json
{"type":"ready","msg":"Connected on none"}
{"type":"hardware_event","pin":"D2","value":1}
{"type":"execution_complete"}
```

`hardware_event` is emitted for `EVT:` / `EVT_A:` frames from the firmware.
With `-port none` there is no firmware, so events never fire but every script
still runs and ends with `execution_complete`.

### Messages (client → monitor)

```
(LISP FORM)...\n
__HIL_END__\n
```

Multiple scripts may be sent; each is executed as it is terminated. The
monitor exits when stdin closes.
