GPIO tools
GPIO write/read for tethered boards, the Uno Q bridge, the serial transport, and hardware context files.
GPIO tools let your agent drive and sense pins on a connected board through plain function calls. The two core tools — gpio_write and gpio_read — work the same way for every tethered board (Raspberry Pi Pico, Arduino Uno, ESP32, STM32 Nucleo) because they all speak the same Revka serial JSON protocol. This page covers those two tools, the serial transport that carries them, the hardware_capabilities discovery tool, the Arduino Uno Q Bridge variant that runs over a TCP socket, and the hardware context files that teach the agent about your specific board.
Use this page when you want the agent to flip an LED, read a button, or check which pins a board exposes. If Revka runs directly on a Raspberry Pi (not tethered over USB), use the native gpio_rpi_* tools instead — see Raspberry Pi (self-hosted). To connect and flash a board first, see Hardware quickstart and Flashing firmware.
GPIO Write (gpio_write)
Section titled “GPIO Write (gpio_write)”gpio_write sets a GPIO pin HIGH or LOW on a registered device. The agent calls it as a function; you typically trigger it with natural language (“turn on pin 25”).
| Parameter | Type | Required | Meaning |
|---|---|---|---|
pin | integer | yes | GPIO pin number |
value | integer | yes | 1 = HIGH (on), 0 = LOW (off) |
device | string | no | Device alias, e.g. pico0, arduino0. Auto-selected when exactly one GPIO-capable device is registered; required when multiple boards are present. |
A typical agent invocation:
User: Turn on pin 25Agent: gpio_write(pin=25, value=1)
# With more than one board connected:Agent: gpio_write(device="pico0", pin=25, value=1)Under the hood the tool sends one newline-delimited JSON line over the device transport and reads one line back:
// Host → Device{"cmd":"gpio_write","params":{"pin":25,"value":1}}// Device → Host{"ok":true,"data":{"pin":25,"value":1,"state":"HIGH"}}On success the tool returns a line like GPIO 25 set HIGH on pico0. Values other than 0 or 1 are rejected before any I/O, and a missing pin or value returns a parameter error.
GPIO Read (gpio_read)
Section titled “GPIO Read (gpio_read)”gpio_read reads the current HIGH/LOW state of a pin. It uses the same transport and the same auto-selection rules as gpio_write.
| Parameter | Type | Required | Meaning |
|---|---|---|---|
pin | integer | yes | GPIO pin number to read |
device | string | no | Device alias; auto-selected if only one GPIO device is registered |
Agent: gpio_read(pin=25)# or, with multiple boards:Agent: gpio_read(device="pico0", pin=25)Wire exchange:
// Host → Device{"cmd":"gpio_read","params":{"pin":25}}// Device → Host{"ok":true,"data":{"pin":25,"value":1,"state":"HIGH"}}The tool output includes both the numeric value and the text state, for example:
GPIO 25 is HIGH (1) on pico0Which GPIO tool runs
Section titled “Which GPIO tool runs”gpio_write and gpio_read are the same tool names across very different transports. Revka substitutes the right implementation based on how the board is registered, so the agent never has to choose.
| Setup | Tools | Transport |
|---|---|---|
| Tethered Pico / Arduino / ESP32 / Nucleo over USB | gpio_write, gpio_read | Serial JSON protocol (this page) |
| Revka running natively on a Raspberry Pi | gpio_rpi_write, gpio_rpi_read, gpio_rpi_blink | Direct /dev/gpiomem via rppal — see Raspberry Pi (self-hosted) |
Arduino Uno Q with transport = "bridge" | gpio_write, gpio_read | Bridge TCP socket on 127.0.0.1:9999 (below) |
| Total Phase Aardvark adapter | gpio_aardvark | 8-pin bitmask over USB — see Aardvark I2C/SPI/GPIO & datasheets |
Serial Peripheral Transport
Section titled “Serial Peripheral Transport”All tethered boards reach their GPIO through the serial transport, which carries the Revka serial JSON protocol over a serial port. You configure it implicitly by setting transport = "serial" on a board entry.
[peripherals]enabled = true
[[peripherals.boards]]board = "nucleo-f401re"transport = "serial"path = "/dev/ttyACM0"baud = 115200| Field | Type | Default | Meaning |
|---|---|---|---|
path | string | — | Serial port path (e.g. /dev/ttyACM0, /dev/cu.usbmodem101) |
baud | integer | 115200 | Serial baud rate |
Two behaviors are worth knowing:
- Lazy open. The port is opened on the first command, not at daemon startup. The daemon starts cleanly even if the board is unplugged at boot — plug it in and the first
gpio_writeopens the connection. - Firmware ping handshake. On first connection the transport sends a
pingand expects a Revka firmware response within 300 ms. Boards that do not answer with Revka firmware are not treated as GPIO devices.
The wire contract is the newline-delimited ZcCommand / ZcResponse pair shown throughout this page: a host command (cmd + params) for each request, and a device response (ok + data, plus error when ok is false). Both firmware and host must agree on this format, so the Pico, Arduino, ESP32, and Nucleo all implement it identically.
Discover available pins (hardware_capabilities)
Section titled “Discover available pins (hardware_capabilities)”Before writing to a pin, the agent can ask each serial board which pins it exposes and which pin drives the onboard LED. The hardware_capabilities tool queries the firmware’s capabilities command and reports the result.
| Parameter | Type | Required | Meaning |
|---|---|---|---|
board | string | no | Filter to a single board name. Omit to query every configured serial board. |
Agent: hardware_capabilities()Output: arduino0: gpio [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], led_pin 13This tool is only registered when the hardware feature is built and serial boards are configured. The firmware must implement the capabilities command in its serial JSON handler; the Revka Arduino firmware enables it alongside gpio_read and gpio_write. If no board matches the filter, the tool reports that capabilities are not supported.
Arduino Uno Q Bridge GPIO Tools
Section titled “Arduino Uno Q Bridge GPIO Tools”The Arduino Uno Q is a Linux board with a companion MCU. Instead of a serial port, GPIO goes through a small Bridge app (Python + MCU socket server) that listens on TCP port 9999 and exposes the MCU’s pins to the Linux side. When you configure the board with transport = "bridge", Revka transparently swaps the standard gpio_read / gpio_write tools for socket-backed implementations — the agent uses the same tool names.
[[peripherals.boards]]board = "arduino-uno-q"transport = "bridge"Calling the tools is identical to the serial case:
User: Turn on pin 13 on the ArduinoAgent: gpio_write(pin=13, value=1)Internally the Bridge tools open a TCP connection to 127.0.0.1:9999 and send a space-delimited, newline-terminated line — for example gpio_write 13 1\n for a write or gpio_read 13\n for a read — then read the reply.
| Timeout | Value |
|---|---|
| Connection | 5 s |
| Response | 3 s |
Hardware Context Files
Section titled “Hardware Context Files”GPIO tools work on raw pin numbers, but the agent reasons better when it knows what each pin does on your board. Revka loads markdown from ~/.revka/hardware/ at boot and injects it into the LLM system prompt, so you can teach the agent about your hardware without touching code. Three kinds of files are supported:
| Path | Purpose |
|---|---|
~/.revka/hardware/HARDWARE.md | Global hardware notes shared across every device |
~/.revka/hardware/devices/<alias>.md | Per-device profile, named for the session alias (e.g. pico0.md) |
~/.revka/hardware/skills/*.md | Hardware skills, loaded in alphabetical order by filename |
-
Write global notes. Capture board-agnostic rules and pin conventions.
Terminal window cat > ~/.revka/hardware/HARDWARE.md << 'EOF'# Hardware Notes- Pin 25 is the onboard LED on Pico- Use device_exec for blink loopsEOF -
Add a device profile. Name the file after the device alias so it loads only when that board is present.
Terminal window mkdir -p ~/.revka/hardware/devicescat > ~/.revka/hardware/devices/pico0.md << 'EOF'# pico0 — Raspberry Pi PicoPort: /dev/cu.usbmodem1101Use pin 25 for the onboard LED.EOF -
Restart the daemon so the boot subsystem re-reads the directory and injects the new context.
How loading works:
- Files are plain markdown — no schema or frontmatter required.
- Sections are joined with double newlines when injected into the system prompt; missing files are silently skipped, and empty files are ignored.
- Device profiles load only for aliases that are actually registered in the session.