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)

  1. Auto-start on USB connect — clock, ROM emulation, and RESET release happen automatically. No commands are needed for the CPU to run.

  2. Generate PHI2 — a GP28 square wave at 0.2 Hz (5 s per cycle) for step-by-step learning. Configurable in firmware for faster speeds.

  3. Reset control — GP27 starts as OUTPUT LOW, then releases to INPUT (the pull-up runs the CPU) once USB is connected.

  4. ROM emulation — a 32 KB rom_image[] in SRAM, mapped to CPU $8000–$FFFF. When A15 = 1, drive GP15–GP22 from rom_image[addr & 0x7FFF]; when A15 = 0, the data bus is Hi-Z. Implemented with GPIO polling (reliable at 100 kHz–1 MHz on this build; PIO + DMA is a future upgrade).

  5. Built-in demo program — a tiny loop at $8000 that writes $05 then $14 (20 decimal) to $4000.

  6. Hardware API — structured host control over USB-CDC serial (see Hardware API).

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 rw)
uint16_t hardware_api_last_addr(void)
bool hardware_api_is_reading(void)
bool hardware_api_monitor_enabled(void)
struct hw_context_t
#include <hardware_api.h>

Public Members

uint8_t *rom_image
size_t rom_size
bool *rom_active
float *current_hz
void (*reset_assert)(void)
void (*reset_release)(void)

Serial framing (protocol.h)

Defines

CTRL_ENQ
CTRL_ACK
CTRL_STX
CTRL_EOT
CTRL_NACK
PROTO_JSON_MAX
PROTO_BINARY_MAX

Functions

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)