65 lines
No EOL
1.7 KiB
Python
65 lines
No EOL
1.7 KiB
Python
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) |