# NeuroAR EEG SNN, XIAO ESP32S3 + ADS1292

A local EEG inference project: a small spiking (LIF) readout runs on the XIAO ESP32S3, reads one EEG channel from an ADS1292 over SPI, extracts band features on the board, and predicts a state. Training happens on a laptop in Python; the board runs the exported model with no cloud.

No trained model or recordings are shipped. An EEG model is person- and device-specific (it depends on the individual, the electrode placement, and the exact ADS1292 board), so `model_weights.py` here is a neutral heuristic starter and predictions stay hidden until you train your own. Record your own labelled data, train, and deploy with the steps below.

## Folder map

- `firmware_micropython/` files copied to the board.
- `dashboard/` browser dashboard + Node server (see `dashboard/README.md`).
- `tools/` host-side Python: capture, training, signal check.
- `data/` your captured CSVs go here (format in `data/README.md`).
- `models/` archived/generated models.
- `firmware_downloads/` the MicroPython binary for the XIAO.

## Hardware pins (glasses board v1)

| Signal | GPIO | XIAO label |
|---|---:|---|
| ADS1292 DIN / MOSI | 7 | D8 |
| ADS1292 SCLK | 8 | D9 |
| ADS1292 DOUT / MISO | 9 | D10 |
| ADS1292 CS | 1 | D0 |
| ADS1292 DRDY | 3 | D2 |
| ADS1292 RESET/PWDN | 4 | D3 |

The firmware sets the ADS1292 to internal reference, 500 SPS, gain 6.

## Run it

From this folder, flash MicroPython (binary in `firmware_downloads/`), then copy the firmware and start the dashboard. Replace `PORT` with your XIAO serial port (`/dev/cu.usbmodem*` on macOS).

```bash
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt

mpremote connect PORT fs cp firmware_micropython/*.py :
mpremote connect PORT reset

cd dashboard && npm start          # open http://localhost:5176
```

## Record, train, deploy

Easiest path is from the dashboard (`Server USB` → pick a label → `Record + Save` → repeat for 2+ labels → `Train + Deploy`). The command-line equivalent:

```bash
# check the signal first; if RMS/peak-to-peak are huge, fix electrode contact
python tools/check_signal_quality.py PORT --seconds 6

python tools/capture_serial.py PORT rest 60 data/rest.csv
python tools/capture_serial.py PORT blink 60 data/blink.csv

python tools/train_snn.py --data data/*.csv --out firmware_micropython/model_weights.py
mpremote connect PORT fs cp firmware_micropython/model_weights.py :
mpremote connect PORT reset
```

The trainer uses `--transform auto` (it scores raw vs. a gain-robust transform with leave-one-row-out validation and exports the better one). Collect several short sessions per label across days/placements; a few dozen rows is a demo, not a reliable model.

## Serial format

```text
RAW,ms,frames,eeg_uv,diag_uv
FEATURE,ms,frames,prediction,confidence,f0..f6   # f0..f4 bands, f5 rms, f6 blink_peak
```

Only `eeg_uv` feeds the model; `diag_uv` is the unused ADS1292 channel, shown so it isn't mistaken for a second electrode.

## Safety

Not a medical device. Don't connect electrodes to a person while the board is plugged into a non-isolated computer, charger, or hub. For human EEG, run from battery with proper isolation.

---

*Documentation generated with AI assistance.*
