micropython: add micropython component
This commit is contained in:
35
components/language/micropython/examples/rp2/pio_1hz.py
Normal file
35
components/language/micropython/examples/rp2/pio_1hz.py
Normal file
@@ -0,0 +1,35 @@
|
||||
# Example using PIO to blink an LED and raise an IRQ at 1Hz.
|
||||
|
||||
import time
|
||||
from machine import Pin
|
||||
import rp2
|
||||
|
||||
|
||||
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
|
||||
def blink_1hz():
|
||||
# fmt: off
|
||||
# Cycles: 1 + 1 + 6 + 32 * (30 + 1) = 1000
|
||||
irq(rel(0))
|
||||
set(pins, 1)
|
||||
set(x, 31) [5]
|
||||
label("delay_high")
|
||||
nop() [29]
|
||||
jmp(x_dec, "delay_high")
|
||||
|
||||
# Cycles: 1 + 7 + 32 * (30 + 1) = 1000
|
||||
set(pins, 0)
|
||||
set(x, 31) [6]
|
||||
label("delay_low")
|
||||
nop() [29]
|
||||
jmp(x_dec, "delay_low")
|
||||
# fmt: on
|
||||
|
||||
|
||||
# Create the StateMachine with the blink_1hz program, outputting on Pin(25).
|
||||
sm = rp2.StateMachine(0, blink_1hz, freq=2000, set_base=Pin(25))
|
||||
|
||||
# Set the IRQ handler to print the millisecond timestamp.
|
||||
sm.irq(lambda p: print(time.ticks_ms()))
|
||||
|
||||
# Start the StateMachine.
|
||||
sm.active(1)
|
27
components/language/micropython/examples/rp2/pio_exec.py
Normal file
27
components/language/micropython/examples/rp2/pio_exec.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# Example using PIO to turn on an LED via an explicit exec.
|
||||
#
|
||||
# Demonstrates:
|
||||
# - using set_init and set_base
|
||||
# - using StateMachine.exec
|
||||
|
||||
import time
|
||||
from machine import Pin
|
||||
import rp2
|
||||
|
||||
# Define an empty program that uses a single set pin.
|
||||
@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW)
|
||||
def prog():
|
||||
pass
|
||||
|
||||
|
||||
# Construct the StateMachine, binding Pin(25) to the set pin.
|
||||
sm = rp2.StateMachine(0, prog, set_base=Pin(25))
|
||||
|
||||
# Turn on the set pin via an exec instruction.
|
||||
sm.exec("set(pins, 1)")
|
||||
|
||||
# Sleep for 500ms.
|
||||
time.sleep(0.5)
|
||||
|
||||
# Turn off the set pin via an exec instruction.
|
||||
sm.exec("set(pins, 0)")
|
@@ -0,0 +1,46 @@
|
||||
# Example using PIO to wait for a pin change and raise an IRQ.
|
||||
#
|
||||
# Demonstrates:
|
||||
# - PIO wrapping
|
||||
# - PIO wait instruction, waiting on an input pin
|
||||
# - PIO irq instruction, in blocking mode with relative IRQ number
|
||||
# - setting the in_base pin for a StateMachine
|
||||
# - setting an irq handler for a StateMachine
|
||||
# - instantiating 2x StateMachine's with the same program and different pins
|
||||
|
||||
import time
|
||||
from machine import Pin
|
||||
import rp2
|
||||
|
||||
|
||||
@rp2.asm_pio()
|
||||
def wait_pin_low():
|
||||
wrap_target()
|
||||
|
||||
wait(0, pin, 0)
|
||||
irq(block, rel(0))
|
||||
wait(1, pin, 0)
|
||||
|
||||
wrap()
|
||||
|
||||
|
||||
def handler(sm):
|
||||
# Print a (wrapping) timestamp, and the state machine object.
|
||||
print(time.ticks_ms(), sm)
|
||||
|
||||
|
||||
# Instantiate StateMachine(0) with wait_pin_low program on Pin(16).
|
||||
pin16 = Pin(16, Pin.IN, Pin.PULL_UP)
|
||||
sm0 = rp2.StateMachine(0, wait_pin_low, in_base=pin16)
|
||||
sm0.irq(handler)
|
||||
|
||||
# Instantiate StateMachine(1) with wait_pin_low program on Pin(17).
|
||||
pin17 = Pin(17, Pin.IN, Pin.PULL_UP)
|
||||
sm1 = rp2.StateMachine(1, wait_pin_low, in_base=pin17)
|
||||
sm1.irq(handler)
|
||||
|
||||
# Start the StateMachine's running.
|
||||
sm0.active(1)
|
||||
sm1.active(1)
|
||||
|
||||
# Now, when Pin(16) or Pin(17) is pulled low a message will be printed to the REPL.
|
45
components/language/micropython/examples/rp2/pio_pwm.py
Normal file
45
components/language/micropython/examples/rp2/pio_pwm.py
Normal file
@@ -0,0 +1,45 @@
|
||||
# Example of using PIO for PWM, and fading the brightness of an LED
|
||||
|
||||
from machine import Pin
|
||||
from rp2 import PIO, StateMachine, asm_pio
|
||||
from time import sleep
|
||||
|
||||
|
||||
@asm_pio(sideset_init=PIO.OUT_LOW)
|
||||
def pwm_prog():
|
||||
# fmt: off
|
||||
pull(noblock) .side(0)
|
||||
mov(x, osr) # Keep most recent pull data stashed in X, for recycling by noblock
|
||||
mov(y, isr) # ISR must be preloaded with PWM count max
|
||||
label("pwmloop")
|
||||
jmp(x_not_y, "skip")
|
||||
nop() .side(1)
|
||||
label("skip")
|
||||
jmp(y_dec, "pwmloop")
|
||||
# fmt: on
|
||||
|
||||
|
||||
class PIOPWM:
|
||||
def __init__(self, sm_id, pin, max_count, count_freq):
|
||||
self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin))
|
||||
# Use exec() to load max count into ISR
|
||||
self._sm.put(max_count)
|
||||
self._sm.exec("pull()")
|
||||
self._sm.exec("mov(isr, osr)")
|
||||
self._sm.active(1)
|
||||
self._max_count = max_count
|
||||
|
||||
def set(self, value):
|
||||
# Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse
|
||||
value = max(value, -1)
|
||||
value = min(value, self._max_count)
|
||||
self._sm.put(value)
|
||||
|
||||
|
||||
# Pin 25 is LED on Pico boards
|
||||
pwm = PIOPWM(0, 25, max_count=(1 << 16) - 1, count_freq=10_000_000)
|
||||
|
||||
while True:
|
||||
for i in range(256):
|
||||
pwm.set(i**2)
|
||||
sleep(0.01)
|
105
components/language/micropython/examples/rp2/pio_uart_rx.py
Normal file
105
components/language/micropython/examples/rp2/pio_uart_rx.py
Normal file
@@ -0,0 +1,105 @@
|
||||
# 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,
|
||||
fifo_join=PIO.JOIN_RX,
|
||||
)
|
||||
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()
|
44
components/language/micropython/examples/rp2/pio_uart_tx.py
Normal file
44
components/language/micropython/examples/rp2/pio_uart_tx.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# Example using PIO to create a UART TX interface
|
||||
|
||||
from machine import Pin
|
||||
from rp2 import PIO, StateMachine, asm_pio
|
||||
|
||||
UART_BAUD = 115200
|
||||
PIN_BASE = 10
|
||||
NUM_UARTS = 8
|
||||
|
||||
|
||||
@asm_pio(sideset_init=PIO.OUT_HIGH, out_init=PIO.OUT_HIGH, out_shiftdir=PIO.SHIFT_RIGHT)
|
||||
def uart_tx():
|
||||
# fmt: off
|
||||
# Block with TX deasserted until data available
|
||||
pull()
|
||||
# Initialise bit counter, assert start bit for 8 cycles
|
||||
set(x, 7) .side(0) [7]
|
||||
# Shift out 8 data bits, 8 execution cycles per bit
|
||||
label("bitloop")
|
||||
out(pins, 1) [6]
|
||||
jmp(x_dec, "bitloop")
|
||||
# Assert stop bit for 8 cycles total (incl 1 for pull())
|
||||
nop() .side(1) [6]
|
||||
# fmt: on
|
||||
|
||||
|
||||
# Now we add 8 UART TXs, on pins 10 to 17. Use the same baud rate for all of them.
|
||||
uarts = []
|
||||
for i in range(NUM_UARTS):
|
||||
sm = StateMachine(
|
||||
i, uart_tx, freq=8 * UART_BAUD, sideset_base=Pin(PIN_BASE + i), out_base=Pin(PIN_BASE + i)
|
||||
)
|
||||
sm.active(1)
|
||||
uarts.append(sm)
|
||||
|
||||
# We can print characters from each UART by pushing them to the TX FIFO
|
||||
def pio_uart_print(sm, s):
|
||||
for c in s:
|
||||
sm.put(ord(c))
|
||||
|
||||
|
||||
# Print a different message from each UART
|
||||
for i, u in enumerate(uarts):
|
||||
pio_uart_print(u, "Hello from UART {}!\n".format(i))
|
59
components/language/micropython/examples/rp2/pio_ws2812.py
Normal file
59
components/language/micropython/examples/rp2/pio_ws2812.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# Example using PIO to drive a set of WS2812 LEDs.
|
||||
|
||||
import array, time
|
||||
from machine import Pin
|
||||
import rp2
|
||||
|
||||
# Configure the number of WS2812 LEDs.
|
||||
NUM_LEDS = 8
|
||||
|
||||
|
||||
@rp2.asm_pio(
|
||||
sideset_init=rp2.PIO.OUT_LOW,
|
||||
out_shiftdir=rp2.PIO.SHIFT_LEFT,
|
||||
autopull=True,
|
||||
pull_thresh=24,
|
||||
)
|
||||
def ws2812():
|
||||
# fmt: off
|
||||
T1 = 2
|
||||
T2 = 5
|
||||
T3 = 3
|
||||
wrap_target()
|
||||
label("bitloop")
|
||||
out(x, 1) .side(0) [T3 - 1]
|
||||
jmp(not_x, "do_zero") .side(1) [T1 - 1]
|
||||
jmp("bitloop") .side(1) [T2 - 1]
|
||||
label("do_zero")
|
||||
nop() .side(0) [T2 - 1]
|
||||
wrap()
|
||||
# fmt: on
|
||||
|
||||
|
||||
# Create the StateMachine with the ws2812 program, outputting on Pin(22).
|
||||
sm = rp2.StateMachine(0, ws2812, freq=8_000_000, sideset_base=Pin(22))
|
||||
|
||||
# Start the StateMachine, it will wait for data on its FIFO.
|
||||
sm.active(1)
|
||||
|
||||
# Display a pattern on the LEDs via an array of LED RGB values.
|
||||
ar = array.array("I", [0 for _ in range(NUM_LEDS)])
|
||||
|
||||
# Cycle colours.
|
||||
for i in range(4 * NUM_LEDS):
|
||||
for j in range(NUM_LEDS):
|
||||
r = j * 100 // (NUM_LEDS - 1)
|
||||
b = 100 - j * 100 // (NUM_LEDS - 1)
|
||||
if j != i % NUM_LEDS:
|
||||
r >>= 3
|
||||
b >>= 3
|
||||
ar[j] = r << 16 | b
|
||||
sm.put(ar, 8)
|
||||
time.sleep_ms(50)
|
||||
|
||||
# Fade out.
|
||||
for i in range(24):
|
||||
for j in range(NUM_LEDS):
|
||||
ar[j] = ar[j] >> 1 & 0x7F7F7F
|
||||
sm.put(ar, 8)
|
||||
time.sleep_ms(50)
|
25
components/language/micropython/examples/rp2/pwm_fade.py
Normal file
25
components/language/micropython/examples/rp2/pwm_fade.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Example using PWM to fade an LED.
|
||||
|
||||
import time
|
||||
from machine import Pin, PWM
|
||||
|
||||
|
||||
# Construct PWM object, with LED on Pin(25).
|
||||
pwm = PWM(Pin(25))
|
||||
|
||||
# Set the PWM frequency.
|
||||
pwm.freq(1000)
|
||||
|
||||
# Fade the LED in and out a few times.
|
||||
duty = 0
|
||||
direction = 1
|
||||
for _ in range(8 * 256):
|
||||
duty += direction
|
||||
if duty > 255:
|
||||
duty = 255
|
||||
direction = -1
|
||||
elif duty < 0:
|
||||
duty = 0
|
||||
direction = 1
|
||||
pwm.duty_u16(duty * duty)
|
||||
time.sleep(0.001)
|
Reference in New Issue
Block a user