-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rp2: Add new port to Raspberry Pi RP2 microcontroller.
This commit adds a new port "rp2" which targets the new Raspberry Pi RP2040 microcontroller. The build system uses pure cmake (with a small Makefile wrapper for convenience). The USB driver is TinyUSB, and there is a machine module with most of the standard classes implemented. Some examples are provided in the examples/rp2/ directory. Work done in collaboration with Graham Sanderson. Signed-off-by: Damien George <damien@micropython.org>
- Loading branch information
Showing
44 changed files
with
5,509 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) |
Oops, something went wrong.