Aardvark I2C/SPI/GPIO & datasheets
The Total Phase Aardvark adapter tools and the datasheet management workflow.
The Total Phase Aardvark is a USB host adapter that turns your machine into an I2C/SPI master with eight bonus GPIO pins. When one is plugged in, Revka registers it as a device (aardvark0) and exposes six bus-level tools the agent can call: scan the I2C bus, read and write I2C registers, run a full-duplex SPI transfer, drive the adapter’s GPIO header, and look up component datasheets.
Use this page when you want an agent to talk to bench electronics — temperature sensors, EEPROMs, SPI flash, port expanders — over a real I2C or SPI bus. It covers the five Aardvark tools, the datasheet workflow, the aardvark-sys crate and its aardvark.so library, and the REVKA_AARDVARK_LIB override. For tethered-MCU GPIO and the native Raspberry Pi tools see GPIO tools; to connect your first board see the Hardware quickstart.
How the Aardvark fits in
Section titled “How the Aardvark fits in”At daemon start, the hardware boot routine asks aardvark-sys whether any adapters are connected. For each one found it registers a device alias (aardvark0, aardvark1, …, USB VID 0x2B76), attaches an AardvarkTransport, and appends the six Aardvark tools to the agent’s tool registry. If no adapter is present — or the aardvark.so library can’t be loaded — the crate runs in stub mode: discovery returns an empty list, no tools are loaded, and nothing crashes.
The stack is layered. Each tool the agent calls turns into a ZcCommand, the transport translates that into aardvark-sys calls, and aardvark-sys is the only layer that touches the C library:
| Layer | File | Role |
|---|---|---|
| Tools | src/hardware/aardvark_tools.rs | Validate agent JSON, resolve the device, build a ZcCommand, return text. |
| Transport | src/hardware/aardvark.rs | Translate ZcCommand ↔ aardvark-sys calls; open a handle per command. |
| FFI bindings | crates/aardvark-sys/src/lib.rs | Safe Rust over the Total Phase C library, loaded at runtime. |
I2C tools
Section titled “I2C tools”The three I2C tools share one optional device argument — the Aardvark alias to target. With a single adapter connected it is auto-selected, so you can omit it; with several, pass device="aardvark0". Addresses and bytes are taken as decimal integers and reported back in hex.
I2C Scan (i2c_scan)
Section titled “I2C Scan (i2c_scan)”Probes every 7-bit address from 0x08 to 0x77 with a one-byte read and returns the addresses that acknowledge. This is the usual first step: identify what’s on the bus, then look up each device’s datasheet.
Agent call: i2c_scan()Output: I2C scan found 2 device(s): 0x48, 0x68When the bus is empty the tool reports I2C scan complete — no devices found on the bus.
| Parameter | Type | Required | Meaning |
|---|---|---|---|
device | string | no | Aardvark alias; auto-selected when only one adapter is connected. |
I2C Read (i2c_read)
Section titled “I2C Read (i2c_read)”Reads bytes from an I2C device. When register is supplied, the tool performs the standard register-read pattern (write the register address, then read); without it, it does a plain read from the device address.
Agent call: i2c_read(addr=72, register=0, len=2)Output: I2C read from addr 0x48: [0xAB, 0xCD]addr=72 is 0x48; register=0 is the register to read from.
| Parameter | Type | Required | Default | Meaning |
|---|---|---|---|---|
device | string | no | auto | Aardvark alias. |
addr | integer | yes | — | I2C device address in decimal (e.g. 72 for 0x48). |
register | integer | no | — | Register address to read from; triggers a write-then-read. |
len | integer | no | 1 | Number of bytes to read. |
I2C Write (i2c_write)
Section titled “I2C Write (i2c_write)”Writes a sequence of bytes to an I2C device — for example, a configuration-register write.
Agent call: i2c_write(addr=72, bytes=[1, 96])Output: I2C write to addr 0x48: 2 byte(s) writtenThis writes [0x01, 0x60] to the device at 0x48.
| Parameter | Type | Required | Meaning |
|---|---|---|---|
device | string | no | Aardvark alias. |
addr | integer | yes | I2C device address in decimal. |
bytes | array of integers | yes | Bytes to write; each value must be a valid u8 (0–255). |
SPI Transfer (spi_transfer)
Section titled “SPI Transfer (spi_transfer)”Performs a full-duplex SPI transfer: the bytes you send are clocked out while the same number of bytes are clocked in and returned. A classic use is reading the JEDEC ID from an SPI flash chip.
Agent call: spi_transfer(bytes=[0x9F, 0x00, 0x00])Output: SPI transfer complete. Received: [0x00, 0xEF, 0x40]| Parameter | Type | Required | Meaning |
|---|---|---|---|
device | string | no | Aardvark alias; auto-selected when only one adapter is connected. |
bytes | array of integers | yes | Bytes to send; the received buffer has the same length. |
Aardvark GPIO (gpio_aardvark)
Section titled “Aardvark GPIO (gpio_aardvark)”The Aardvark exposes eight GPIO pins on its 10-pin expansion header. Unlike the per-pin gpio_write/gpio_rpi_write tools, gpio_aardvark operates on all eight pins at once using one-byte bitmasks — bit N corresponds to pin N.
Set pin directions and levels with action="set"; read the current pin states with action="get".
# Set pin 0 as output, drive it HIGHAgent call: gpio_aardvark(action="set", direction=0b00000001, value=0b00000001)Output: Aardvark GPIO set — direction: 0b00000001, value: 0b00000001
# Read all eight pinsAgent call: gpio_aardvark(action="get")Output: Aardvark GPIO pins: 0b00000001 (0x01)| Parameter | Type | Required | Meaning |
|---|---|---|---|
device | string | no | Aardvark alias. |
action | string | yes | set or get. |
direction | integer | for set | Bitmask of pin directions: 1 = output, 0 = input. |
value | integer | for set | Bitmask of output levels: 1 = HIGH, 0 = LOW. |
Outputs are shown in both binary (0b…) and hex so the bitmask is easy to read back.
Datasheet management (datasheet)
Section titled “Datasheet management (datasheet)”The datasheet tool ties the bus tools into a practical loop: scan the bus, identify a device, fetch its datasheet, and use the register map to program it. Datasheets are stored as PDFs under ~/.revka/hardware/datasheets/. It is registered alongside the other Aardvark tools when an adapter is detected.
It has four actions:
| Action | Required fields | What it does |
|---|---|---|
search | device_name | Returns a suggested web-search query for the datasheet (does not run the search itself). |
download | device_name, url | Downloads the PDF at url and saves it as <device_name>.pdf. |
list | — | Lists the PDFs cached in the datasheets directory. |
read | device_name | Returns the local path (and extracted text, with rag-pdf) of a cached datasheet. |
// 1. Get a search query (the agent then runs it with its web_search tool){ "action": "search", "device_name": "LM75" }
// 2. Download once you have the URL{ "action": "download", "device_name": "LM75", "url": "https://www.ti.com/lit/ds/symlink/lm75.pdf" }
// 3. List what's cached{ "action": "list" }
// 4. Get the cached file path / text{ "action": "read", "device_name": "LM75" }A typical bench session
Section titled “A typical bench session”-
Scan the bus to find connected devices.
i2c_scan() → I2C scan found 1 device(s): 0x48 -
Look up the datasheet. The agent calls
datasheet(action="search", device_name="LM75"), runs the returned query withweb_search, then downloads the PDF withdatasheet(action="download", …). -
Read a register using the address and register map from the datasheet.
i2c_read(addr=72, register=0, len=2) → I2C read from addr 0x48: [0x19, 0x00] -
Write configuration if needed.
i2c_write(addr=72, bytes=[1, 96]) → I2C write to addr 0x48: 2 byte(s) written
The aardvark-sys crate
Section titled “The aardvark-sys crate”aardvark-sys (crates/aardvark-sys) provides safe Rust bindings to the Total Phase Aardvark C library. It loads aardvark.so dynamically at runtime via libloading, and is the only place in Revka where unsafe is permitted. It exposes device enumeration (find_devices), an RAII open/close handle, I2C enable/read/write/scan, SPI enable/transfer, and GPIO set/get. You never call this crate directly — it sits under AardvarkTransport — but its behavior explains how the tools degrade and recover.
Key behaviors:
- Stub mode is graceful. If
aardvark.socan’t be found or loaded, every method returns an error andfind_devices()returns[]. The daemon starts normally with the Aardvark tools simply absent. - Free adapters only.
find_devices()returns the port numbers of free adapters; ports already in use by another process are filtered out. - Per-command handles. A fresh handle is opened for each command and its
Dropimpl callsaa_closeautomatically, so connections are never left open.
Library setup and REVKA_AARDVARK_LIB
Section titled “Library setup and REVKA_AARDVARK_LIB”The Aardvark tools depend on the proprietary aardvark.so shared library from Total Phase. aardvark-sys searches for it at runtime in this order:
- The path in the
REVKA_AARDVARK_LIBenvironment variable (a full path toaardvark.so). <workspace>/crates/aardvark-sys/vendor/aardvark.so(the development default).aardvark.sonext to the running binary (for deployment).aardvark.soin the current working directory.
The first candidate that loads wins. To point Revka at a library installed elsewhere, set the override before starting the daemon:
export REVKA_AARDVARK_LIB=/opt/totalphase/aardvark.sorevka daemon$env:REVKA_AARDVARK_LIB = "C:\TotalPhase\aardvark.dll"revka daemonIf no candidate resolves, aardvark-sys logs that no library was found and falls back to stub mode — the daemon still runs, just without Aardvark tools.
Verify the setup
Section titled “Verify the setup”After plugging in an adapter and starting the daemon, confirm the tools loaded:
curl http://127.0.0.1:42617/tools | grep -E "i2c_scan|spi_transfer|gpio_aardvark|datasheet"If those tool names appear, the adapter was detected and the library loaded. If they’re missing: check that the binary was built with --features hardware, that the adapter was connected before the daemon started, and that aardvark.so is on the search path (set REVKA_AARDVARK_LIB if needed). For a quick end-to-end check, ask the agent to scan the bus:
revka agent -m "Scan the I2C bus with the Aardvark"See Status, health, config & tools endpoints for the /tools endpoint and revka doctor, status & self-test for diagnostics.