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
|
|
|
|
|
2024-05-14 18:42:12 +02:00
|
|
|
LEDS = 5
|
2024-05-14 17:26:58 +02:00
|
|
|
PIN = Pin(16)
|
2024-05-14 18:42:12 +02:00
|
|
|
DELAY = 5
|
2024-05-14 17:26:58 +02:00
|
|
|
|
|
|
|
"""
|
|
|
|
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)
|
|
|
|
|
2024-05-14 18:42:12 +02:00
|
|
|
def transition_step(src_hex: int, tgt_hex: int, prog: float):
|
|
|
|
src_hex += int(( (tgt_hex >> 16) - (src_hex >> 16) ) * prog) << 16
|
|
|
|
src_hex += int(( (tgt_hex >> 8 & 0xFF) - (src_hex >> 8 & 0xFF) ) * prog) << 8
|
|
|
|
src_hex += int(( (tgt_hex & 0xFF) - (src_hex & 0xFF) ) * prog)
|
|
|
|
|
|
|
|
return src_hex
|
|
|
|
|
|
|
|
cols = [randint(0, 0xFFFFFF) for i in range(LEDS)]
|
|
|
|
cols_new = cols[1:] + [randint(0, 0xFFFFFF)]
|
|
|
|
|
2024-05-14 17:26:58 +02:00
|
|
|
while True:
|
2024-05-14 18:42:12 +02:00
|
|
|
cols.pop(0)
|
|
|
|
cols.append(cols_new[-1])
|
|
|
|
cols_new.pop(0)
|
|
|
|
cols_new.append(randint(0, 0xFFFFFF))
|
|
|
|
|
|
|
|
for i in range(0, 100):
|
|
|
|
for l in range(LEDS):
|
|
|
|
cold = transition_step(cols[l], cols_new[l], i / 100)
|
|
|
|
sm.put(cold, 8) # I don't know why 8 not 24
|
|
|
|
sleep_ms(DELAY)
|
|
|
|
|