This commit is contained in:
jimmy 2023-12-30 13:39:55 +00:00
parent f8515bddde
commit bd703c33e3
1 changed files with 88 additions and 61 deletions

View File

@ -1,43 +1,18 @@
# Example based on pio_ws2812.py, but modified to use # Example using PIO to drive a set of WS2812 LEDs.
# a DMA channel to push out the data to the PIO
import array, time import array, time
from machine import Pin from machine import Pin
import rp2 import rp2
from time import sleep
import dma
# Configure the number of WS2812 LEDs. # Configure the number of WS2812 LEDs.
NUM_LEDS = 9 NUM_LEDS = 256
PIN_NUM = 0
brightness = 0.2
SM = 0 @rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_RIGHT, autopull=True, pull_thresh=24)
PIO0_BASE = 0x50200000
PIO1_BASE = 0x50300000
PIO0_BASE_TXF0 = PIO0_BASE+0x10
PIO0_BASE_TXF1 = PIO0_BASE+0x14
PIO0_BASE_TXF2 = PIO0_BASE+0x18
PIO0_BASE_TXF3 = PIO0_BASE+0x1c
PIO1_BASE_TXF0 = PIO1_BASE+0x10
PIO1_BASE_TXF1 = PIO1_BASE+0x14
PIO1_BASE_TXF2 = PIO1_BASE+0x18
PIO1_BASE_TXF3 = PIO1_BASE+0x1c
if SM < 4:
TFX = PIO0_BASE+0x10 + SM * 4
else:
TFX = PIO1_BASE+0x10 + (SM-4) * 4
@rp2.asm_pio(
sideset_init=rp2.PIO.OUT_LOW,
out_shiftdir=rp2.PIO.SHIFT_LEFT,
autopull=True,
pull_thresh=24,
)
def ws2812(): def ws2812():
# fmt: off
T1 = 2 T1 = 2
T2 = 5 T2 = 5
T3 = 3 T3 = 3
@ -49,39 +24,91 @@ def ws2812():
label("do_zero") label("do_zero")
nop() .side(0) [T2 - 1] nop() .side(0) [T2 - 1]
wrap() wrap()
# fmt: on
class WS2812B:
# Create the StateMachine with the ws2812 program, outputting on Pin(2). def __init__(self, num_leds, pin_num, brightness, state_machine):
sm = rp2.StateMachine(SM, ws2812, freq=8_000_000, sideset_base=Pin(0)) # 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_num))
# Start the StateMachine, it will wait for data on its FIFO. # Start the StateMachine, it will wait for data on its FIFO.
sm.active(1) self.sm.active(1)
# Dummy data # Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)]) self.ar = array.array("I", [0 for _ in range(num_leds)])
r = 0xff self.num_leds = num_leds
g = 0xff self.brightness = brightness
b = 0xff self.pio_dma = dma.PIO_DMA_Transfer(state_machine+4, state_machine, 32, num_leds)
ar[0] = 0xff000000
ar[1] = 0x00ff0000 def show(self):
ar[2] = 0x0000ff00 #self.sm.put(self.ar)
ar[3] = r<<24 + g<<16 + b<<8 self.pio_dma.start_transfer(self.ar)
def set(self, i, color):
self.ar[i] = int((color[1]<<16)*self.brightness) + int((color[0]<<8)*self.brightness) + int(color[2]*self.brightness)
def fill(self, color):
for i in range(len(self.ar)):
self.set(i, color)
def wait(self):
return self.pio_dma.busy()
def color_chase(self, color, wait):
for i in range(self.num_leds):
self.set(i, color)
time.sleep(wait)
self.show()
time.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)
# starts the transfer, using DMA channel 0 def rainbow_cycle(self, wait):
def dma_out(): for j in range(255):
import dma, uctypes for i in range(self.num_leds):
dma.init_channels() rc_index = (i * 256 // self.num_leds) + j
d0=dma.CHANNELS[0] self.set(i, self.wheel(rc_index & 255))
d0.CTRL_TRIG.EN = 0 self.show()
d0.TRANS_COUNT = NUM_LEDS time.sleep(wait)
d0.READ_ADDR = uctypes.addressof(ar)
d0.WRITE_ADDR = TFX
d0.CTRL_TRIG.INCR_WRITE = 0
d0.CTRL_TRIG.INCR_READ = 1
d0.CTRL_TRIG.DATA_SIZE = 2
d0.CTRL_TRIG.EN = 1
dma_out() BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE)
if __name__ == "__main__":
ws0 = WS2812B(256, 1, 1, 1)
ws1 = WS2812B(256, 2, 1, 5)
ws2 = WS2812B(256, 3, 1, 6)
while True:
for color in ws0.COLORS:
ws0.fill(color)
ws0.show()
ws1.fill(color)
ws1.show()
ws2.fill(color)
ws2.show()
time.sleep(1) time.sleep(1)