diff --git a/ws2812.py b/ws2812.py index 384de56..c9d9c2f 100644 --- a/ws2812.py +++ b/ws2812.py @@ -1,17 +1,11 @@ -# Example using PIO to drive a set of WS2812 LEDs. import array, time from machine import Pin import rp2 from time import sleep -import uasyncio as asyncio +import dma -# Configure the number of WS2812 LEDs. -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) +@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=8) def ws2812(): T1 = 2 T2 = 5 @@ -26,59 +20,30 @@ def ws2812(): wrap() class WS2812B: - def __init__(self, num_leds, pin_num, brightness, sm): - # Create the StateMachine with the ws2812 program, outputting on 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. + def __init__(self, num_leds, pin, state_machine, brightness=0.1, invert=False): + self.sm = rp2.StateMachine(state_machine, ws2812, freq=8_000_000, sideset_base=Pin(pin)) self.sm.active(1) - - # 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.ar = bytearray(num_leds*3) self.num_leds = num_leds self.brightness = brightness + self.invert = invert + self.pio_dma = dma.PIO_DMA_Transfer(state_machine+4, state_machine, 8, num_leds*3) - ########################################################################## - async def pixels_show(self): - self.sm.put(self.ar, 8) - await asyncio.sleep(0.00001) + def show(self): + self.pio_dma.start_transfer(self.ar) - def pixels_set(self, i, color): - self.ar[i] = (int(color[1]*self.brightness)<<16) + (int(color[0]*self.brightness)<<8) + int(color[2]*self.brightness) - - def pixels_fill(self, color): - for i in range(len(self.ar)): - self.pixels_set(i, color) - - async def color_chase(self, color, wait): + def set(self, i, color): + self.ar[i*3] = int(color[1]*self.brightness) + self.ar[i*3+1] = int(color[0]*self.brightness) + self.ar[i*3+2] = int(color[2]*self.brightness) + + def fill(self, color): for i in range(self.num_leds): - self.pixels_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) + self.set(i, color) + def busy(self): + return self.pio_dma.busy() + BLACK = (0, 0, 0) RED = (255, 0, 0) YELLOW = (255, 150, 0) @@ -88,23 +53,16 @@ class WS2812B: PURPLE = (180, 0, 255) WHITE = (255, 255, 255) 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__": - loop = asyncio.get_event_loop() - asyncio.create_task(run(0,0)) - asyncio.create_task(run(17,1)) - asyncio.create_task(run(18,2)) - loop.run_forever() - + num_leds, pin, sm, brightness = 10, 0, 0, 1 + ws0 = WS2812B(num_leds, pin, sm, brightness) + while True: + for color in ws0.COLORS: + ws0.fill(color) + ws0.show() + time.sleep(1) + + -