From 3ea05e499d52beaecf4c9c54a67510ac031fe27b Mon Sep 17 00:00:00 2001 From: Tim Radvan Date: Mon, 1 Feb 2021 20:07:19 +0000 Subject: [PATCH] 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 --- examples/rp2/pio_uart_rx.py | 104 ++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 examples/rp2/pio_uart_rx.py diff --git a/examples/rp2/pio_uart_rx.py b/examples/rp2/pio_uart_rx.py new file mode 100644 index 0000000000..41dfde3dad --- /dev/null +++ b/examples/rp2/pio_uart_rx.py @@ -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()