from machine import Pin from rp2 import PIO, StateMachine, asm_pio from time import sleep_ms, sleep_us from random import randint LEDS = 3 PIN = Pin(16) """ inspired by https://github.com/raspberrypi/pico-micropython-examples/blob/master/pio/pio_ws2812.py I made this for no other purpose than learning took me a few hours to understand pio, but if I did it you can too ws2811 has different timing: 0 - 250ns, then 1000ns 1 - 600ns, then 650ns rpi cpu cycle = 8ns to make things easier, we can split timing: 0 -> 250ns high + 350 low + 650 low 1 -> 250ns high + 350 high + 650 low p1 -> 250ns = 31.25 cycles p2 -> 350ns = 43.75 cycles p3 -> 650ns = 81.25 cycles decimal, but it's fine if it's off by some, so we can round """ @asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def prog(): label("loop") # 3rd part nop().side(0).delay(14) # 15 nop().side(0).delay(14) # 30 nop().side(0).delay(14) # 45 nop().side(0).delay(14) # 60 nop().side(0).delay(14) # 75 out(x, 1).side(0).delay(5) # 81. get one bit of color # 1st part nop().side(1).delay(15) # 16 jmp(not_x, "zero").side(1).delay(14) # 31. check if zero # 2nd part for 1 bit nop().side(1).delay(14) # 15 nop().side(1).delay(14) # 30 jmp("loop").side(1).delay(12) # 43 # 2nd part for 0 bit label("zero") nop().side(0).delay(14) # 15 nop().side(0).delay(14) # 30 nop().side(0).delay(12) # 43 sm = StateMachine(0, prog, sideset_base=PIN) sm.active(1) while True: for i in range(LEDS): sm.put(randint(0, 0xFFFFFF), 8) # I still don't know why 8 not 24 sleep_ms(500)