Skip to content

Micropython

Christian Köhlke edited this page Jan 27, 2026 · 1 revision

PIO

The following code load the PIO-progamm "pio_code" into a PIO. The programm itself pulse a pin. The FIFO is used to communicate how often (steps) the pin should be pulsed and the delay between each step. The FIFO has 4*32bits. The controller checks in a loop whether there is a free slot in the FIFO and send alternating data (few slow pulse; many fast pulses) to the PIO programm.

import time
from machine import Pin
import rp2

# Global variable to store step count (incremented by IRQ handler)
step_count = 0


class PioData:

    def __init__(self, steps=0, delay=0):
        """
        PIO data structure to hold steps and delay

        Args:
            steps (int): Number of toggle cycles
            delay (int): Delay between toggles in ms
        """
        self.steps = steps
        self.delay = delay

    def put(self, sm: rp2.StateMachine, pio_freq=2000):
        delay = int((self.delay / 1000) * pio_freq)
        print(f"Putting steps: {self.steps}, delay: {delay} (PIO cycles)")
        data = ((self.steps & 0xFFFF) << 16) | (delay & 0xFFFF)
        sm.put(data)


@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
def pio_code():
    wrap_target()
    pull(block)
    out(y, 16)
    out(isr, 16)

    label("step_loop")

    set(pins, 1)
    set(pins, 0)

    irq(0)

    mov(x, isr)
    label("low_delay")
    jmp(x_dec, "low_delay")

    jmp(y_dec, "step_loop")

    wrap()


# IRQ Handler: Called when PIO triggers IRQ after each step
def pio_irq_handler(sm):
    global step_count
    step_count += 1


# Initialize PIO
PIN = 17
sm = rp2.StateMachine(0, pio_code, freq=2000, set_base=Pin(PIN))
sm.irq(handler=pio_irq_handler)
sm.active(1)

pio_data1 = PioData()
pio_data1.steps = 3
pio_data1.delay = 1000
pio_data1.put(sm)

pio_data2 = PioData()
pio_data2.steps = 10
pio_data2.delay = 100
pio_data2.put(sm)

pio_data = [pio_data1, pio_data2]

print("Press Ctrl+C to stop")

current_data_index = 0

try:
    while True:
        time.sleep(1)

        free_slots = 4 - sm.tx_fifo()
        print(f"TX FIFO free slots: {free_slots}")
        if free_slots > 0:
            pio_data[current_data_index].put(sm)
            current_data_index = (current_data_index + 1) % len(pio_data)
except KeyboardInterrupt:
    sm.irq(handler=None)
    sm.active(0)
    print("\nStopped")

Clone this wiki locally