pico-python/ws2811.py

65 lines
1.7 KiB
Python
Raw Normal View History

2024-05-14 17:26:58 +02:00
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)