# Architecture

HIL-OS V9.5 is a hardware-in-the-loop stack. LISP scripts written by the user
are executed on a host **monitor** that streams compact commands over UART to an
embedded **firmware**, or — with no hardware at all — runs fully headless, or is
transpiled into an Arduino sketch for the CRUMB circuit simulator.

## Processes

### 1. hil-orchestrator (`firmware/monitor.go`)

The host monitor. A single Go binary with four modes:

| Mode | Trigger | Behaviour |
|------|---------|-----------|
| Interactive | `hil-orchestrator -port COM3 -baud 9600` | REPL over the serial link |
| Headless IPC | `hil-orchestrator -ipc -port none` | JSON-lines protocol on stdin/stdout, no serial |
| Send | `hil-orchestrator -send <file>` | Inject a script into a running monitor via TCP:9000 |
| Build | `hil-orchestrator -build <file>` | Compile a script to Intel HEX, then exit |

The monitor contains the **LISP engine** (tokenizer → parser → evaluator), the
hardware abstraction (`hwWrite`, `hwRead`, events, autopilot), the serial link
with CRC, and the background TCP control server on port 9000.

### 2. Firmware (`firmware.go`)

TinyGo firmware for the Blinky node (ATmega328P — same chip as Arduino Uno/Nano).
Compiles with TinyGo (`//go:build tinygo`). Parses `ACTION TYPE PIN VAL1
VAL2|CRC\r` frames, executes them, and returns `ACK`. Also runs standalone in
**autopilot** mode. Build and flash via `hil-cli firmware build/flash`.

### 3. hil-cli (`firmware/main.go` with `-tags cli`)

A package-manager-style CLI: scaffold projects, manage macro packages, run /
simulate / build scripts, generate CRUMB circuits, and **flash firmware to real
Arduino hardware** (Uno/Nano/Mega). See [CLI.md](CLI.md).

### 4. hil-node (`hil-node/hil.js`)

A Node.js wrapper: spawns the monitor in headless IPC mode and exposes a
promise-based API. See [NODE-API.md](NODE-API.md).

### 5. CRUMB simulator (external)

A Unity/IL2CPP circuit simulator with an Arduino Nano. `hil-cli crumb`
transpiles LISP → Arduino C, injects it into a `.cru` circuit file, and opens
the simulator. See [CRUMB-SIMULATION.md](CRUMB-SIMULATION.md).

## Data flow (wired)

```
LISP script ──▶ hil-orchestrator
                     │  eval AST
                     │  hw*() abstraction
                     ▼
              UART frames "W D 13 1 0|<crc>\r"
                     │
                     ▼
              firmware executeHardware(action,typ,pin,val1,val2)
                     ▼
              machine pins (digitalWrite, setPWM, reads)
                     ▼
              replies: ACK, "D:pin:val", "A:pin:val", "I:addr:val", "(t h)"
```

## Data flow (headless / IPC)

```
LISP script ──▶ hil-cli simulate ──▶ hil-orchestrator -ipc -port none
                                          │  JSON lines on stdin/stdout
                                          ▼
                                  {"type":"ready", ...}
                                  {"type":"hardware_event", ...}
                                  {"type":"execution_complete", ...}
```

The IPC mode short-circuits the UART: hardware writes and reads operate on the
in-memory pin state, so scripts execute identically with or without a node.

## Data flow (CRUMB simulation)

```
LISP script ──▶ hil-cli crumb
                     │  transpile (AST → C)
                     │  cIdent() name sanitization
                     │  GenerateCRU (clone .cru template + inject sketch)
                     │  XML well-formedness check
                     │  Copy to Documents + register in recent.log
                     ▼
              simulation/<name>.cru ──▶ CRUMBWPF.exe (open)
                     ▼
              simulated Nano runs setup()/loop()
              Serial output → CRUMB serial monitor
```

The transpiler generates Arduino-compatible C with:
- `cIdent()` sanitization (hyphens → underscores, all user names uppercased)
- Run-once guard (`if (!_hil_ran)` wrapping)
- MAP degenerate range guard (prevents division-by-zero)
- Empty else suppression (cleaner output)
- TONE support (passive buzzer on D11)
- Sensor mocks (LM35 via analogRead, ULTRASONIC/DHT mock values)
- Peripheral mocks (I2C, LCD, MP3, SD, NeoPixel via Serial.print)

## Events

The monitor supports event-driven scripts:

- `ON-EVENT pin mode macro` — digital edge events (`E D <pin> <mode> 0`)
- `ON-CHANGE type pin threshold macro` — analog rate-of-change (`C <t> <p> <th> 0`)

Firmware events are received as `EVT:D:pin:val` / `EVT_A:A:pin:val` frames and
mapped to the registered macro names in `eventHooks`.

## Autopilot

`AUTOPILOT-BEGIN` clears the firmware's command buffer (`A C 0 0 0`), subsequent
`WRITE`/`READ`/`TONE`/`PULSE`/`DELAY` ops compile to `A W`/`A D` records in MCU
RAM, and `AUTOPILOT-END` commits (`A E 1 0 0`). The node then runs the recorded
sequence standalone on boot.
