examples/rp2: Add pio_uart_rx.py example.
This was adapted from the `pio/uart_rx` example from the `pico-examples` repository: https://github.com/raspberrypi/pico-examples/blob/master/pio/uart_rx/uart_rx.pio It demonstrates the `jmp_pin` feature in action. Signed-off-by: Tim Radvan <tim@tjvr.org>
This commit is contained in:
parent
7a9027fd5d
commit
3ea05e499d
|
@ -0,0 +1,104 @@
|
|||
# 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,
|
||||
)
|
||||
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()
|
Loading…
Reference in New Issue