Wire the Pico to UART-driven preset selection, add pattern modules and presets data, remove old p2p/settings code, and update tests and LED driver. Made-with: Cursor
82 lines
2.4 KiB
Python
82 lines
2.4 KiB
Python
import math
|
|
import sys
|
|
if "lib" not in sys.path:
|
|
sys.path.insert(0, "lib")
|
|
if "../lib" not in sys.path:
|
|
sys.path.insert(0, "../lib")
|
|
from ws2812 import WS2812B
|
|
import time
|
|
|
|
# --- Roll: N buffers (length = max strip), gradient full -> off; sequence through strips ---
|
|
N_BUFFERS = 32 # more buffers = smoother transition
|
|
|
|
STRIP_CONFIG = (
|
|
(2, 291),
|
|
(3, 290),
|
|
(4, 283),
|
|
(7, 278),
|
|
(0, 275),
|
|
(28, 278),
|
|
(29, 283),
|
|
(6, 290),
|
|
)
|
|
|
|
strips = []
|
|
sm = 0
|
|
for pin, num_leds in STRIP_CONFIG:
|
|
print(pin, num_leds)
|
|
ws = WS2812B(num_leds, pin, sm, brightness=1.0)
|
|
strips.append(ws)
|
|
sm += 1
|
|
|
|
num_strips = len(strips)
|
|
max_leds = max(ws.num_leds for ws in strips)
|
|
# Color when "on" (R, G, B); GRB order in buffer
|
|
ROLL_COLOR = (0, 255, 120) # cyan-green
|
|
|
|
|
|
def make_gradient_buffers(n_buffers, max_leds, color):
|
|
"""Create n_buffers buffers, each max_leds long. Buffer 0 = full brightness, last = off.
|
|
Gradient is logarithmic (perceptually smoother: more steps near full, fewer near off). GRB order."""
|
|
out = []
|
|
for j in range(n_buffers):
|
|
# log gradient: scale = 255 * log(1 + (n - 1 - j)) / log(n) so 255 at j=0, 0 at j=n-1
|
|
if n_buffers <= 1:
|
|
scale = 255
|
|
elif j >= n_buffers - 1:
|
|
scale = 0
|
|
else:
|
|
# 1 + (n_buffers - 1 - j) runs from n_buffers down to 1
|
|
scale = int(255 * math.log(1 + (n_buffers - 1 - j)) / math.log(n_buffers))
|
|
scale = min(255, scale)
|
|
buf = bytearray(max_leds * 3)
|
|
r = (color[0] * scale) // 255
|
|
g = (color[1] * scale) // 255
|
|
b = (color[2] * scale) // 255
|
|
for i in range(max_leds):
|
|
o = i * 3
|
|
buf[o] = g & 0xFF
|
|
buf[o + 1] = r & 0xFF
|
|
buf[o + 2] = b & 0xFF
|
|
out.append(buf)
|
|
return out
|
|
|
|
|
|
# N buffers: first full, last off, gradient between
|
|
buffers = make_gradient_buffers(N_BUFFERS, max_leds, ROLL_COLOR)
|
|
|
|
step = 0
|
|
delay_ms = 50
|
|
# Deadline-based loop: no extra pause at rotation wrap, smooth continuous roll
|
|
next_ms = time.ticks_ms()
|
|
|
|
while True:
|
|
for i, strip in enumerate(strips):
|
|
buf_index = (step + i) % N_BUFFERS
|
|
strip.show(buffers[buf_index], 0)
|
|
step += 1 # unbounded; wrap only in index so no hitch at cycle end
|
|
next_ms += delay_ms
|
|
# Sleep until next frame time (handles drift, no pause at wrap)
|
|
while time.ticks_diff(next_ms, time.ticks_ms()) > 0:
|
|
time.sleep_ms(1)
|