Switch to DMA

This commit is contained in:
jimmy 2024-01-31 07:39:54 +00:00
parent b60f27acf6
commit 1f39ed4f08
1 changed files with 28 additions and 70 deletions

View File

@ -1,17 +1,11 @@
# Example using PIO to drive a set of WS2812 LEDs.
import array, time import array, time
from machine import Pin from machine import Pin
import rp2 import rp2
from time import sleep from time import sleep
import uasyncio as asyncio import dma
# Configure the number of WS2812 LEDs. @rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=8)
NUM_LEDS = 256
PIN_NUM = 0
brightness = 0.2
@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2812(): def ws2812():
T1 = 2 T1 = 2
T2 = 5 T2 = 5
@ -26,59 +20,30 @@ def ws2812():
wrap() wrap()
class WS2812B: class WS2812B:
def __init__(self, num_leds, pin_num, brightness, sm): def __init__(self, num_leds, pin, state_machine, brightness=0.1, invert=False):
# Create the StateMachine with the ws2812 program, outputting on pin self.sm = rp2.StateMachine(state_machine, ws2812, freq=8_000_000, sideset_base=Pin(pin))
self.sm = rp2.StateMachine(sm, ws2812, freq=8_000_000, sideset_base=Pin(pin_num))
# Start the StateMachine, it will wait for data on its FIFO.
self.sm.active(1) self.sm.active(1)
self.ar = bytearray(num_leds*3)
# Display a pattern on the LEDs via an array of LED RGB values.
self.ar = array.array("I", [0 for _ in range(num_leds)])
self.num_leds = num_leds self.num_leds = num_leds
self.brightness = brightness self.brightness = brightness
self.invert = invert
self.pio_dma = dma.PIO_DMA_Transfer(state_machine+4, state_machine, 8, num_leds*3)
########################################################################## def show(self):
async def pixels_show(self): self.pio_dma.start_transfer(self.ar)
self.sm.put(self.ar, 8)
await asyncio.sleep(0.00001)
def pixels_set(self, i, color): def set(self, i, color):
self.ar[i] = (int(color[1]*self.brightness)<<16) + (int(color[0]*self.brightness)<<8) + int(color[2]*self.brightness) self.ar[i*3] = int(color[1]*self.brightness)
self.ar[i*3+1] = int(color[0]*self.brightness)
def pixels_fill(self, color): self.ar[i*3+2] = int(color[2]*self.brightness)
for i in range(len(self.ar)):
self.pixels_set(i, color) def fill(self, color):
async def color_chase(self, color, wait):
for i in range(self.num_leds): for i in range(self.num_leds):
self.pixels_set(i, color) self.set(i, color)
await asyncio.sleep(wait)
await self.pixels_show()
await asyncio.sleep(0.2)
def wheel(self, pos):
# Input a value 0 to 255 to get a color value.
# The colours are a transition r - g - b - back to r.
if pos < 0 or pos > 255:
return (0, 0, 0)
if pos < 85:
return (255 - pos * 3, pos * 3, 0)
if pos < 170:
pos -= 85
return (0, 255 - pos * 3, pos * 3)
pos -= 170
return (pos * 3, 0, 255 - pos * 3)
async def rainbow_cycle(self, wait):
for j in range(255):
for i in range(self.num_leds):
rc_index = (i * 256 // self.num_leds) + j
self.pixels_set(i, self.wheel(rc_index & 255))
await self.pixels_show()
await asyncio.sleep(wait)
def busy(self):
return self.pio_dma.busy()
BLACK = (0, 0, 0) BLACK = (0, 0, 0)
RED = (255, 0, 0) RED = (255, 0, 0)
YELLOW = (255, 150, 0) YELLOW = (255, 150, 0)
@ -88,23 +53,16 @@ class WS2812B:
PURPLE = (180, 0, 255) PURPLE = (180, 0, 255)
WHITE = (255, 255, 255) WHITE = (255, 255, 255)
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE) COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE)
async def run(pin, sm):
ws = WS2812B(10, pin, 1, sm)
ws.pixels_fill(ws.RED)
while True:
await ws.rainbow_cycle(0)
if __name__ == "__main__": if __name__ == "__main__":
loop = asyncio.get_event_loop() num_leds, pin, sm, brightness = 10, 0, 0, 1
asyncio.create_task(run(0,0)) ws0 = WS2812B(num_leds, pin, sm, brightness)
asyncio.create_task(run(17,1)) while True:
asyncio.create_task(run(18,2)) for color in ws0.COLORS:
loop.run_forever() ws0.fill(color)
ws0.show()
time.sleep(1)