Hardware API Client¶
Romulan’s HardwareAPI class wraps the Piclone firmware’s v1 JSON protocol over a framed USB-serial link. Use it from Python scripts, tests, or the romulan hardware CLI subcommands.
For the full firmware-side protocol specification, see the Piclone Hardware API docs.
Quick start¶
from romulan.hardware_api import HardwareAPI
with HardwareAPI("/dev/ttyACM0") as api:
print(api.status())
api.reset(assert_reset=True)
api.upload_rom(open("bin/rom.bin", "rb").read())
api.reset(assert_reset=False)
capture = api.read_until_stp(max_cycles=500)
print(capture.reason, len(capture.cycles))
HardwareAPI opens the serial port on construction and closes it on exit from a with block.
Framed protocol¶
Every command and response travels inside a byte-level frame:
Step |
Direction |
Byte |
Meaning |
|---|---|---|---|
1 |
Host → Pico |
|
Start frame |
2 |
Host → Pico |
|
Payload follows |
3 |
Pico → Host |
|
Ready for payload |
4 |
Host → Pico |
JSON bytes |
Command or response |
5 |
Host → Pico |
|
End of payload |
6 |
Pico → Host |
|
Accepted or rejected |
All JSON payloads include "v": 1. An optional "id" field is echoed in responses.
Commands¶
Command |
Purpose |
|---|---|
|
Upload 32 KB ROM (begin → chunk × N → commit) |
|
Assert or release CPU reset |
|
Enable or disable ASCII bus monitor |
|
Read current CPU address |
|
Capture bus cycles until STP or max cycles |
|
Query firmware state (clock, reset, ROM, monitor) |
ROM upload¶
The upload is a three-phase sequence with base64-encoded chunks (max 1,476 raw bytes each):
{"v":1,"cmd":"upload_rom","action":"begin","size":32768}{"v":1,"cmd":"upload_rom","action":"chunk","offset":N,"data":"<base64>"}— repeated{"v":1,"cmd":"upload_rom","action":"commit"}— returnsreset_vector
upload_rom() disables the ASCII monitor and flushes serial input before transferring.
Bus capture¶
Send {"v":1,"cmd":"read","until":"stp","max_cycles":N} and receive streaming event frames:
{"type":"event","event":"cycle",...}— one CPU bus cycle{"type":"event","event":"done",...}— capture finished
read_until_stp() disables the monitor before starting capture.
Important notes¶
Do not open a plain serial monitor on the port while using the framed protocol — unstructured output corrupts framing.
Disable the ASCII monitor before scripted upload or capture (the client methods do this automatically).
The ROM image in Pico SRAM is lost on power cycle — re-upload after each reboot.
Python API reference¶
See the Python API page for autodoc of HardwareAPI, protocol_v1, and related modules.