Firmware¶
The firmware lives in src/
and is built with the Raspberry Pi Pico SDK. It targets the Pico 2 (PICO_BOARD=pico2)
and bundles a small JSON parser (cJSON) for the v1 Hardware API.
What it does (auto-run)¶
Auto-start on USB connect: clock, ROM emulation, and RESET release happen automatically. No commands are needed for the CPU to run.
Generate PHI2: a GP28 square wave at 1 kHz by default (~1 ms per cycle) for faster CI and capture. The
readcommand accepts optionalphi2_hz(0.1–1000 Hz).Reset control: GP27 starts as OUTPUT LOW, then releases to INPUT (the pull-up runs the CPU) once USB is connected.
ROM emulation: a 32 KB
rom_image[]in SRAM, mapped to CPU$8000–$FFFF. When A15 = 1 and RWB is high (read cycle), drive GP15–GP22 fromrom_image[addr & 0x7FFF]; otherwise the data bus is Hi-Z so the CPU can drive writes. Implemented with GPIO polling (reliable at the supported 0.1–1000 Hz PHI2 range; PIO + DMA is a future upgrade for higher clocks).Built-in demo program: matches Romulan
demo.txt— writes$05then$14then$08to RAM-side stores and ends inSTP($DB) so capture stops cleanly.Hardware API: structured host control over USB-CDC serial (see Hardware API). The
readcommand returns batchedcyclesevents (up tobatch_sizecycles perread_eventpoll);drivecan force the data bus for diagnostics.
Build¶
export PICO_SDK_PATH=~/vsarm/pico-sdk # your SDK checkout path
cd src
mkdir -p build && cd build
cmake ..
make
The build produces build/piclone.uf2. The project bundles pico_sdk_import.cmake, so no
separate SDK-import step is needed. See Host Tools for flashing and
uploading ROMs.
C API reference (Doxygen)¶
The following is generated from the firmware sources by Doxygen and rendered via Breathe.
Hardware API (hardware_api.h)¶
Functions
-
void hardware_api_init(const hw_context_t *ctx)¶
-
void hardware_api_handle_enq(void)¶
-
void hardware_api_on_bus_cycle(uint16_t addr, uint8_t data, bool rwb_pin)¶
-
void hardware_api_poll(void)¶
-
uint16_t hardware_api_last_addr(void)¶
-
bool hardware_api_is_reading(void)¶
-
bool hardware_api_monitor_enabled(void)¶
-
bool hardware_api_exchange_active(void)¶
-
bool hardware_api_drive_enabled(void)¶
-
uint8_t hardware_api_drive_value(void)¶
-
void hardware_api_diag_read_reset(uint32_t *calls, uint32_t *edges, uint32_t *high_no_edge, uint32_t *low_no_edge, uint32_t *alarm_fires)¶
-
struct hw_context_t¶
- #include <hardware_api.h>
Serial framing (protocol.h)¶
Typedefs
-
typedef void (*proto_idle_fn)(void)¶
Functions
-
void proto_set_idle_hook(proto_idle_fn fn)¶
-
void proto_idle_pump(void)¶
-
bool proto_read_byte(uint8_t *out, uint32_t timeout_ms)¶
-
bool proto_write_byte(uint8_t b)¶
-
bool proto_send_ack(void)¶
-
bool proto_send_nack(void)¶
-
bool proto_read_frame_payload(uint8_t *buf, size_t buf_size, size_t *out_len)¶
-
bool proto_send_frame(const uint8_t *payload, size_t len)¶