epio
A cycle-accurate RP2350 PIO emulator
Loading...
Searching...
No Matches
Classes | Macros | Typedefs | Enumerations | Functions
epio.h File Reference

epio - A cycle-accurate RP2350 PIO emulator. More...

#include <stdint.h>
#include <stddef.h>
#include <epio_wasm.h>
#include <apio.h>
Include dependency graph for epio.h:

Go to the source code of this file.

Classes

struct  epio_sm_debug_t
 Debug information for a single PIO state machine. More...
 
struct  epio_sm_reg_t
 Configurable registers for a single PIO state machine. More...
 

Macros

#define NUM_GPIOS   48
 Maximum number of supported GPIOs.
 
#define NUM_PIO_BLOCKS   3
 Number of PIO blocks on the RP2350.
 
#define NUM_SMS_PER_BLOCK   4
 Number of state machines per PIO block.
 
#define MAX_FIFO_DEPTH   4
 Maximum TX/RX FIFO depth per state machine.
 
#define NUM_DMA_CHANNELS   16
 Number of DMA channels.
 
#define NUM_IRQS_PER_BLOCK   8
 Number of IRQs per PIO block.
 
#define NUM_INSTRS_PER_BLOCK   32
 Number of instruction slots per PIO block.
 

Typedefs

typedef struct epio_t epio_t
 Opaque epio instance type.
 

Enumerations

enum  epio_float_mode_t { EPIO_FLOAT_LOW = 0 , EPIO_FLOAT_HIGH = 1 , EPIO_FLOAT_RANDOM = 2 }
 Controls the value returned when reading an undriven GPIO pin that has been explicitly configured with no pull resistor (PULL_NONE). More...
 

Functions

EPIO_EXPORT epio_t * epio_init (void)
 Create and initialise a new epio instance.
 
EPIO_EXPORT void epio_free (epio_t *epio)
 Free an epio instance and all associated resources.
 
EPIO_EXPORT void epio_set_sm_debug (epio_t *epio, uint8_t block, uint8_t sm, epio_sm_debug_t *debug)
 Sets debug information for a specific state machine.
 
EPIO_EXPORT void epio_get_sm_debug (epio_t *epio, uint8_t block, uint8_t sm, epio_sm_debug_t *debug)
 Gets the debug information for a specific state machine.
 
EPIO_EXPORT void epio_set_gpiobase (epio_t *epio, uint8_t block, uint32_t gpio_base)
 Set the GPIO base for a PIO block.
 
EPIO_EXPORT uint32_t epio_get_gpiobase (epio_t *epio, uint8_t block)
 Get the GPIO base for a PIO block.
 
EPIO_EXPORT void epio_set_sm_reg (epio_t *epio, uint8_t block, uint8_t sm, epio_sm_reg_t *reg)
 Set the SM configuration registers for a state machine.
 
EPIO_EXPORT void epio_get_sm_reg (epio_t *epio, uint8_t block, uint8_t sm, epio_sm_reg_t *reg)
 Read the current SM configuration registers for a state machine.
 
EPIO_EXPORT void epio_enable_sm (epio_t *epio, uint8_t block, uint8_t sm)
 Enable a state machine for execution.
 
EPIO_EXPORT uint8_t epio_is_sm_enabled (epio_t *epio, uint8_t block, uint8_t sm)
 Check if a state machine is enabled.
 
EPIO_EXPORT void epio_disable_sm (epio_t *epio, uint8_t block, uint8_t sm)
 Disable a state machine.
 
EPIO_EXPORT void epio_set_instr (epio_t *epio, uint8_t block, uint8_t instr_num, uint16_t instr)
 Write a PIO instruction into the instruction memory of a block.
 
EPIO_EXPORT uint16_t epio_get_instr (epio_t *epio, uint8_t block, uint8_t instr_num)
 Read a PIO instruction from the instruction memory of a block.
 
EPIO_EXPORT void epio_force_sm_instr (epio_t *epio, uint8_t block, uint8_t sm, uint16_t instr)
 Emulate a write to a state machine's SMx_INSTR register.
 
EPIO_EXPORT void epio_step_cycles (epio_t *epio, uint32_t cycles)
 Advance all enabled state machines by a number of clock cycles.
 
EPIO_EXPORT uint64_t epio_get_cycle_count (epio_t *epio)
 Return the total number of cycles executed since last reset.
 
EPIO_EXPORT void epio_reset_cycle_count (epio_t *epio)
 Reset the cycle counter to zero.
 
EPIO_EXPORT int32_t epio_wait_tx_fifo (epio_t *epio, uint8_t block, uint8_t sm, int32_t count)
 Wait for a maximum of count cycles until the TX FIFO of a state machine has an entry pushed to it.
 
EPIO_EXPORT uint8_t epio_tx_fifo_depth (epio_t *epio, uint8_t block, uint8_t sm)
 Return the current number of entries in the TX FIFO.
 
EPIO_EXPORT uint8_t epio_rx_fifo_depth (epio_t *epio, uint8_t block, uint8_t sm)
 Return the current number of entries in the RX FIFO.
 
EPIO_EXPORT uint32_t epio_pop_rx_fifo (epio_t *epio, uint8_t block, uint8_t sm)
 Pop a value from the RX FIFO.
 
EPIO_EXPORT uint32_t epio_pop_tx_fifo (epio_t *epio, uint8_t block, uint8_t sm)
 Pop a value from the TX FIFO.
 
EPIO_EXPORT void epio_push_tx_fifo (epio_t *epio, uint8_t block, uint8_t sm, uint32_t value)
 Push a value into the TX FIFO.
 
EPIO_EXPORT void epio_push_rx_fifo (epio_t *epio, uint8_t block, uint8_t sm, uint32_t value)
 Push a value directly into the RX FIFO from the host.
 
EPIO_EXPORT void epio_drive_gpios_ext (epio_t *epio, uint64_t gpios, uint64_t level)
 Drive a set of GPIOs to specified levels from an external source.
 
void epio_set_gpio_input_inverted (epio_t *epio, uint8_t pin, uint8_t inverted)
 Set a GPIO pin as inverted or non-inverted.
 
uint8_t epio_get_gpio_input_inverted (epio_t *epio, uint8_t pin)
 Get the inversion state of a GPIO pin.
 
void epio_set_gpio_output_control (epio_t *epio, uint8_t pin, uint8_t block)
 Set GPIO output control for a pin to a specific block.
 
void epio_clear_gpio_output_control (epio_t *epio, uint8_t pin, uint8_t block)
 Clear GPIO output control for a pin.
 
uint8_t epio_block_can_control_gpio_output (epio_t *epio, uint8_t block, uint8_t pin)
 Check if a block can control the output of a GPIO pin.
 
uint64_t epio_get_gpio_output_control (epio_t *epio, uint8_t block)
 Get the GPIO output control for a block.
 
EPIO_EXPORT uint8_t epio_get_gpio_input (epio_t *epio, uint8_t pin)
 Read the current input level of a single GPIO pin.
 
EPIO_EXPORT void epio_init_gpios (epio_t *epio)
 Reset all GPIOs to their hardware reset defaults.
 
EPIO_EXPORT void epio_set_gpio_force_input_low (epio_t *epio, uint8_t pin, uint8_t force_low)
 Force a GPIO pin configured as an input to present a low level.
 
EPIO_EXPORT void epio_set_gpio_force_input_high (epio_t *epio, uint8_t pin, uint8_t force_high)
 Force a GPIO pin configured as an input to present a high level.
 
EPIO_EXPORT uint8_t epio_get_gpio_force_input_low (epio_t *epio, uint8_t pin)
 Get whether a GPIO pin configured as an input has a forced input level low.
 
EPIO_EXPORT uint8_t epio_get_gpio_force_input_high (epio_t *epio, uint8_t pin)
 Get whether a GPIO pin configured as an input has a forced input level high.
 
EPIO_EXPORT void epio_set_gpio_input (epio_t *epio, uint8_t pin)
 Configure a GPIO pin as an input.
 
EPIO_EXPORT void epio_set_gpio_output (epio_t *epio, uint8_t pin)
 Configure a GPIO pin as an output.
 
EPIO_EXPORT void epio_set_gpio_input_level (epio_t *epio, uint8_t pin, uint8_t level)
 Set the level of a GPIO configured as an input.
 
EPIO_EXPORT void epio_set_gpio_output_level (epio_t *epio, uint8_t pin, uint8_t level)
 Set the level of a GPIO configured as an output.
 
EPIO_EXPORT uint64_t epio_read_pin_states (epio_t *epio)
 Read the current state of all GPIO pins.
 
EPIO_EXPORT uint64_t epio_read_driven_pins (epio_t *epio)
 Read the set of GPIO pins currently being driven by PIO.
 
EPIO_EXPORT uint64_t epio_read_pull_up_pins (epio_t *epio)
 Return a bitmask of all GPIO pins that have a pull-up configured.
 
EPIO_EXPORT uint64_t epio_read_pull_down_pins (epio_t *epio)
 Return a bitmask of all GPIO pins that have a pull-down configured.
 
EPIO_EXPORT void epio_set_gpio_pull_up (epio_t *epio, uint8_t pin, uint8_t enable)
 Enable or disable a pull-up resistor on a GPIO pin.
 
EPIO_EXPORT void epio_set_gpio_pull_down (epio_t *epio, uint8_t pin, uint8_t enable)
 Enable or disable a pull-down resistor on a GPIO pin.
 
EPIO_EXPORT void epio_set_gpio_pull_none (epio_t *epio, uint8_t pin)
 Disable both pull-up and pull-down resistors on a GPIO pin.
 
EPIO_EXPORT uint8_t epio_get_gpio_pull_up (epio_t *epio, uint8_t pin)
 Get the pull-up state of a GPIO pin.
 
EPIO_EXPORT uint8_t epio_get_gpio_pull_down (epio_t *epio, uint8_t pin)
 Get the pull-down state of a GPIO pin.
 
EPIO_EXPORT void epio_set_gpio_input_only (epio_t *epio, uint8_t pin, uint8_t input_only)
 Mark a GPIO pin as input-only (output driver disabled).
 
EPIO_EXPORT uint8_t epio_get_gpio_input_only (epio_t *epio, uint8_t pin)
 Get the input-only state of a GPIO pin.
 
EPIO_EXPORT void epio_set_gpio_drive (epio_t *epio, uint8_t pin, uint8_t strength)
 Set the drive strength for a GPIO output pin.
 
EPIO_EXPORT uint8_t epio_get_gpio_drive (epio_t *epio, uint8_t pin)
 Get the configured drive strength for a GPIO output pin.
 
EPIO_EXPORT void epio_set_gpio_slew_fast (epio_t *epio, uint8_t pin, uint8_t fast)
 Set the slew rate for a GPIO output pin.
 
EPIO_EXPORT uint8_t epio_get_gpio_slew_fast (epio_t *epio, uint8_t pin)
 Get the configured slew rate for a GPIO output pin.
 
EPIO_EXPORT void epio_set_float_mode (epio_t *epio, epio_float_mode_t mode)
 Set the float mode for undriven PULL_NONE pins.
 
EPIO_EXPORT void epio_set_float_seed (epio_t *epio, uint32_t seed)
 Seed the PRNG used by EPIO_FLOAT_RANDOM float mode.
 
EPIO_EXPORT void epio_dma_setup_read_pio_chain (epio_t *epio, uint8_t dma_chan, uint8_t read_block, uint8_t read_sm, uint8_t read_cycles, uint8_t write_block, uint8_t write_sm, uint8_t write_cycles, uint8_t bit_mode)
 Configure a DMA channel (pair) for PIO read access to SRAM.
 
EPIO_EXPORT void epio_dma_setup_capture_pio_ring (epio_t *epio, uint8_t dma_chan, uint8_t src_block, uint8_t src_sm, uint8_t src_cycles, uint32_t ring_base, uint8_t ring_size_log2, uint8_t bit_mode)
 Configure a DMA channel for PIO-capture into a circular SRAM ring.
 
EPIO_EXPORT uint8_t ** epio_dma_capture_write_slot (epio_t *epio, uint8_t dma_chan)
 Get the address of a capture channel's live host write pointer.
 
EPIO_EXPORT uint8_t * epio_get_sram_ptr (epio_t *epio)
 Get a direct pointer to the emulated SRAM buffer.
 
EPIO_EXPORT uint8_t epio_sram_read_byte (epio_t *epio, uint32_t addr)
 Read a byte from the emulated SRAM.
 
EPIO_EXPORT void epio_sram_set (epio_t *epio, uint32_t addr, uint8_t *data, size_t len)
 Write a block of data into the emulated SRAM.
 
EPIO_EXPORT uint16_t epio_sram_read_halfword (epio_t *epio, uint32_t addr)
 Read a halfword (16-bit) from the emulated SRAM.
 
EPIO_EXPORT uint32_t epio_sram_read_word (epio_t *epio, uint32_t addr)
 Read a word (32-bit) from the emulated SRAM.
 
EPIO_EXPORT void epio_sram_write_byte (epio_t *epio, uint32_t addr, uint8_t value)
 Write a byte to the emulated SRAM.
 
EPIO_EXPORT void epio_sram_write_halfword (epio_t *epio, uint32_t addr, uint16_t value)
 Write a halfword (16-bit) to the emulated SRAM.
 
EPIO_EXPORT void epio_sram_write_word (epio_t *epio, uint32_t addr, uint32_t value)
 Write a word (32-bit) to the emulated SRAM.
 
EPIO_EXPORT uint8_t epio_peek_sm_pc (epio_t *epio, uint8_t block, uint8_t sm)
 Get the current program counter (PC) for a state machine.
 
EPIO_EXPORT uint32_t epio_peek_sm_x (epio_t *epio, uint8_t block, uint8_t sm)
 Get the current X register value for a state machine.
 
EPIO_EXPORT uint32_t epio_peek_sm_y (epio_t *epio, uint8_t block, uint8_t sm)
 Get the current Y register value for a state machine.
 
EPIO_EXPORT uint32_t epio_peek_sm_isr (epio_t *epio, uint8_t block, uint8_t sm)
 Get the current Input Shift Register (ISR) value for a state machine.
 
EPIO_EXPORT uint32_t epio_peek_sm_osr (epio_t *epio, uint8_t block, uint8_t sm)
 Get the current Output Shift Register (OSR) value for a state machine.
 
EPIO_EXPORT uint8_t epio_peek_sm_isr_count (epio_t *epio, uint8_t block, uint8_t sm)
 Get the current ISR bit counter for a state machine.
 
EPIO_EXPORT uint8_t epio_peek_sm_osr_count (epio_t *epio, uint8_t block, uint8_t sm)
 Get the current OSR bit counter for a state machine.
 
EPIO_EXPORT uint8_t epio_peek_sm_osr_empty (epio_t *epio, uint8_t block, uint8_t sm)
 Check whether the OSR is considered empty for a state machine.
 
EPIO_EXPORT uint8_t epio_peek_sm_stalled (epio_t *epio, uint8_t block, uint8_t sm)
 Check if a state machine is currently stalled.
 
EPIO_EXPORT uint8_t epio_peek_sm_delay (epio_t *epio, uint8_t block, uint8_t sm)
 Get the current delay counter for a state machine.
 
EPIO_EXPORT uint8_t epio_peek_sm_exec_pending (epio_t *epio, uint8_t block, uint8_t sm)
 Check if a state machine has a pending EXEC instruction.
 
EPIO_EXPORT uint16_t epio_peek_sm_exec_instr (epio_t *epio, uint8_t block, uint8_t sm)
 Get the pending EXEC instruction for a state machine.
 
EPIO_EXPORT uint32_t epio_peek_block_irq (epio_t *epio, uint8_t block)
 Get the current IRQ state bitmask for a PIO block.
 
EPIO_EXPORT uint8_t epio_peek_block_irq_num (epio_t *epio, uint8_t block, uint8_t irq_num)
 Check if a specific IRQ flag is set for a PIO block.
 
EPIO_EXPORT uint32_t epio_peek_rx_fifo (epio_t *epio, uint8_t block, uint8_t sm, uint8_t entry)
 Peek at an entry in the RX FIFO of a state machine without popping it.
 
EPIO_EXPORT uint32_t epio_peek_tx_fifo (epio_t *epio, uint8_t block, uint8_t sm, uint8_t entry)
 Peek at an entry in the TX FIFO of a state machine without popping it.
 
EPIO_EXPORT void epio_set_block_irq (epio_t *epio, uint8_t block, uint8_t irq_num)
 Set an IRQ flag for a PIO block.
 
EPIO_EXPORT void epio_clear_block_irq (epio_t *epio, uint8_t block, uint8_t irq_num)
 Clear an IRQ flag for a PIO block.
 
EPIO_EXPORT epio_t * epio_from_apio (void)
 Create an epio instance configured from the current apio state.
 
EPIO_EXPORT void epio_update_from_apio (epio_t *epio)
 Update a live epio instance from the current accumulated apio state.
 
EPIO_EXPORT int epio_disassemble_sm (epio_t *epio, uint8_t block, uint8_t sm, char *buffer, size_t buffer_size)
 Disassemble the instructions of a state machine.
 

Detailed Description

epio - A cycle-accurate RP2350 PIO emulator.

epio emulates RP2350 PIO state machines on non-RP2350 hosts, enabling deterministic testing and verification of PIO programs without real hardware. It supports all 12 PIO state machines across 3 PIO blocks, running simultaneously.

If used in conjunction with apio, an epio instance can be configured automatically via epio_from_apio(). Otherwise, the instance can be configured manually using the Global API.

Note
Unless otherwise stated, all functions assert that parameters are within valid ranges (e.g. block, sm, and pin indices).

Typedef Documentation

◆ epio_t

typedef struct epio_t epio_t

Opaque epio instance type.

All API functions operate on a pointer to this type. Create with epio_init() or epio_from_apio(), and destroy with epio_free().

Enumeration Type Documentation

◆ epio_float_mode_t

Controls the value returned when reading an undriven GPIO pin that has been explicitly configured with no pull resistor (PULL_NONE).

Does not affect pins with an explicit pull-up or pull-down configured. Default: EPIO_FLOAT_HIGH.

Enumerator
EPIO_FLOAT_LOW 

Undriven PULL_NONE pins read as 0.

EPIO_FLOAT_HIGH 

Undriven PULL_NONE pins read as 1 (default).

EPIO_FLOAT_RANDOM 

Undriven PULL_NONE pins return a PRNG value.

Function Documentation

◆ epio_dma_capture_write_slot()

EPIO_EXPORT uint8_t ** epio_dma_capture_write_slot ( epio_t *  epio,
uint8_t  dma_chan 
)

Get the address of a capture channel's live host write pointer.

Returns a pointer to the capture channel's internal host pointer, which tracks the current ring write position and advances (wrapping) as the ring fills. Intended for emulator test seams that need to observe how far a capture channel has written without polling every cycle.

Parameters
epioThe epio instance.
dma_chanA DMA channel previously configured with epio_dma_setup_capture_pio_ring().
Returns
Address of the channel's live host write pointer.

◆ epio_dma_setup_capture_pio_ring()

EPIO_EXPORT void epio_dma_setup_capture_pio_ring ( epio_t *  epio,
uint8_t  dma_chan,
uint8_t  src_block,
uint8_t  src_sm,
uint8_t  src_cycles,
uint32_t  ring_base,
uint8_t  ring_size_log2,
uint8_t  bit_mode 
)

Configure a DMA channel for PIO-capture into a circular SRAM ring.

Sets up a single "capture" DMA channel that drains the source state machine's RX FIFO into a circular ring buffer in emulated SRAM, mirroring the RP2350 address-monitor DMA. Each pushed word is written into the ring (as an 8-, 16- or 32-bit entry) src_cycles cycles after it is popped, and the channel's write position advances, wrapping within the ring. A consumer can poll the write position to observe how far the ring has filled.

Parameters
epioThe epio instance.
dma_chanDMA channel number (0 to NUM_DMA_CHANNELS-1).
src_blockPIO block index of the source SM (0 to NUM_PIO_BLOCKS-1).
src_smSource SM index (0 to NUM_SMS_PER_BLOCK-1).
src_cyclesTransfer latency in cycles (>= 1).
ring_baseRP2350 SRAM address of the ring buffer. Must be aligned to the ring size (1 << ring_size_log2).
ring_size_log2Log2 of the ring size in bytes.
bit_modeEntry size in bits: 8, 16 or 32.

◆ epio_dma_setup_read_pio_chain()

EPIO_EXPORT void epio_dma_setup_read_pio_chain ( epio_t *  epio,
uint8_t  dma_chan,
uint8_t  read_block,
uint8_t  read_sm,
uint8_t  read_cycles,
uint8_t  write_block,
uint8_t  write_sm,
uint8_t  write_cycles,
uint8_t  bit_mode 
)

Configure a DMA channel (pair) for PIO read access to SRAM.

This sets up the specified DMA channel for use by PIO programs that read from SRAM.

Parameters
epioThe epio instance.
dma_chanDMA channel number (0 to NUM_DMA_CHANNELS-1).
read_blockPIO block index for the read side of the channel (0 to NUM_PIO_BLOCKS-1).
read_smState machine index for the read side of the channel (0 to NUM_SMS_PER_BLOCK-1).
read_cyclesNumber of cycles for the read side of the channel (1 to 255).
write_blockPIO block index for the write side of the channel (0 to NUM_PIO_BLOCKS-1).
write_smState machine index for the write side of the channel (0 to NUM_SMS_PER_BLOCK-1).
write_cyclesNumber of cycles for the write side of the channel (1 to 255).
bit_modeBit mode for the channel: 8, 16 or 32.