2021-02-01 20:07:19 +00:00
|
|
|
# Example using PIO to create a UART RX interface.
|
|
|
|
#
|
|
|
|
# To make it work you'll need a wire connecting GPIO4 and GPIO3.
|
|
|
|
#
|
|
|
|
# Demonstrates:
|
|
|
|
# - PIO shifting in data on a pin
|
|
|
|
# - PIO jmp(pin) instruction
|
|
|
|
# - PIO irq handler
|
|
|
|
# - using the second core via _thread
|
|
|
|
|
|
|
|
import _thread
|
|
|
|
from machine import Pin, UART
|
|
|
|
from rp2 import PIO, StateMachine, asm_pio
|
|
|
|
|
|
|
|
UART_BAUD = 9600
|
|
|
|
|
|
|
|
HARD_UART_TX_PIN = Pin(4, Pin.OUT)
|
|
|
|
PIO_RX_PIN = Pin(3, Pin.IN, Pin.PULL_UP)
|
|
|
|
|
|
|
|
|
|
|
|
@asm_pio(
|
|
|
|
autopush=True,
|
|
|
|
push_thresh=8,
|
|
|
|
in_shiftdir=rp2.PIO.SHIFT_RIGHT,
|
2021-04-02 19:35:18 +01:00
|
|
|
fifo_join=PIO.JOIN_RX,
|
2021-02-01 20:07:19 +00:00
|
|
|
)
|
|
|
|
def uart_rx_mini():
|
|
|
|
# fmt: off
|
|
|
|
# Wait for start bit
|
|
|
|
wait(0, pin, 0)
|
|
|
|
# Preload bit counter, delay until eye of first data bit
|
|
|
|
set(x, 7) [10]
|
|
|
|
# Loop 8 times
|
|
|
|
label("bitloop")
|
|
|
|
# Sample data
|
|
|
|
in_(pins, 1)
|
|
|
|
# Each iteration is 8 cycles
|
|
|
|
jmp(x_dec, "bitloop") [6]
|
|
|
|
# fmt: on
|
|
|
|
|
|
|
|
|
|
|
|
@asm_pio(
|
|
|
|
in_shiftdir=rp2.PIO.SHIFT_RIGHT,
|
|
|
|
)
|
|
|
|
def uart_rx():
|
|
|
|
# fmt: off
|
|
|
|
label("start")
|
|
|
|
# Stall until start bit is asserted
|
|
|
|
wait(0, pin, 0)
|
|
|
|
# Preload bit counter, then delay until halfway through
|
|
|
|
# the first data bit (12 cycles incl wait, set).
|
|
|
|
set(x, 7) [10]
|
|
|
|
label("bitloop")
|
|
|
|
# Shift data bit into ISR
|
|
|
|
in_(pins, 1)
|
|
|
|
# Loop 8 times, each loop iteration is 8 cycles
|
|
|
|
jmp(x_dec, "bitloop") [6]
|
|
|
|
# Check stop bit (should be high)
|
|
|
|
jmp(pin, "good_stop")
|
|
|
|
# Either a framing error or a break. Set a sticky flag
|
|
|
|
# and wait for line to return to idle state.
|
|
|
|
irq(block, 4)
|
|
|
|
wait(1, pin, 0)
|
|
|
|
# Don't push data if we didn't see good framing.
|
|
|
|
jmp("start")
|
|
|
|
# No delay before returning to start; a little slack is
|
|
|
|
# important in case the TX clock is slightly too fast.
|
|
|
|
label("good_stop")
|
|
|
|
push(block)
|
|
|
|
# fmt: on
|
|
|
|
|
|
|
|
|
|
|
|
# The handler for a UART break detected by the PIO.
|
|
|
|
def handler(sm):
|
|
|
|
print("break", time.ticks_ms(), end=" ")
|
|
|
|
|
|
|
|
|
|
|
|
# Function for core1 to execute to write to the given UART.
|
|
|
|
def core1_task(uart, text):
|
|
|
|
uart.write(text)
|
|
|
|
|
|
|
|
|
|
|
|
# Set up the hard UART we're going to use to print characters.
|
|
|
|
uart = UART(1, UART_BAUD, tx=HARD_UART_TX_PIN)
|
|
|
|
|
|
|
|
for pio_prog in ("uart_rx_mini", "uart_rx"):
|
|
|
|
# Set up the state machine we're going to use to receive the characters.
|
|
|
|
sm = StateMachine(
|
|
|
|
0,
|
|
|
|
globals()[pio_prog],
|
|
|
|
freq=8 * UART_BAUD,
|
|
|
|
in_base=PIO_RX_PIN, # For WAIT, IN
|
|
|
|
jmp_pin=PIO_RX_PIN, # For JMP
|
|
|
|
)
|
|
|
|
sm.irq(handler)
|
|
|
|
sm.active(1)
|
|
|
|
|
|
|
|
# Tell core 1 to print some text to UART 1
|
|
|
|
text = "Hello, world from PIO, using {}!".format(pio_prog)
|
|
|
|
_thread.start_new_thread(core1_task, (uart, text))
|
|
|
|
|
|
|
|
# Echo characters received from PIO to the console.
|
|
|
|
for i in range(len(text)):
|
|
|
|
print(chr(sm.get() >> 24), end="")
|
|
|
|
print()
|