From 5821d81cf47318e0d75e7f5976d95c812b21def9 Mon Sep 17 00:00:00 2001 From: jimmy Date: Tue, 19 Dec 2023 10:59:03 +0000 Subject: [PATCH] Add dma_ws2812.py --- dma_ws2812.py | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 dma_ws2812.py diff --git a/dma_ws2812.py b/dma_ws2812.py new file mode 100644 index 0000000..ac32888 --- /dev/null +++ b/dma_ws2812.py @@ -0,0 +1,87 @@ +# Example based on pio_ws2812.py, but modified to use +# a DMA channel to push out the data to the PIO + +import array, time +from machine import Pin +import rp2 + +# Configure the number of WS2812 LEDs. +NUM_LEDS = 9 + +SM = 0 + +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(): + # 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(2). +sm = rp2.StateMachine(SM, ws2812, freq=8_000_000, sideset_base=Pin(0)) + +# Start the StateMachine, it will wait for data on its FIFO. +sm.active(1) + +# Dummy data +ar = array.array("I", [0 for _ in range(NUM_LEDS)]) +r = 0xff +g = 0xff +b = 0xff +ar[0] = 0xff000000 +ar[1] = 0x00ff0000 +ar[2] = 0x0000ff00 +ar[3] = r<<24 + g<<16 + b<<8 + + +# starts the transfer, using DMA channel 0 +def dma_out(): + import dma, uctypes + dma.init_channels() + d0=dma.CHANNELS[0] + d0.CTRL_TRIG.EN = 0 + d0.TRANS_COUNT = NUM_LEDS + 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() +time.sleep(1)