Add rainbow test
This commit is contained in:
94
pico/test/rainbow.py
Normal file
94
pico/test/rainbow.py
Normal file
@@ -0,0 +1,94 @@
|
||||
import sys
|
||||
# So "from ws2812 import WS2812B" finds pico/lib when run from device / or test/
|
||||
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
|
||||
|
||||
# --- Rainbow pattern (outside ws2812): pregen double buffer, show via head offset ---
|
||||
|
||||
def hue_to_rgb(hue):
|
||||
"""Hue 0..360 -> (r, g, b). Simple HSV with S=V=1."""
|
||||
h = hue % 360
|
||||
x = 1 - abs((h / 60) % 2 - 1)
|
||||
if h < 60:
|
||||
r, g, b = 1, x, 0
|
||||
elif h < 120:
|
||||
r, g, b = x, 1, 0
|
||||
elif h < 180:
|
||||
r, g, b = 0, 1, x
|
||||
elif h < 240:
|
||||
r, g, b = 0, x, 1
|
||||
elif h < 300:
|
||||
r, g, b = x, 0, 1
|
||||
else:
|
||||
r, g, b = 1, 0, x
|
||||
return (int(r * 255), int(g * 255), int(b * 255))
|
||||
|
||||
|
||||
def make_rainbow_double(num_leds, brightness=1.0):
|
||||
"""Build 2 full rainbow cycles (2*num_leds pixels, GRB). Returns (double_buf, strip_len).
|
||||
head must be in 0..strip_len-1 so DMA reads double_buf[head:head+strip_len] with no copy."""
|
||||
n = 2 * num_leds
|
||||
double_buf = bytearray(n * 3)
|
||||
for i in range(n):
|
||||
hue = (i / n) * 360 * 2
|
||||
r, g, b = hue_to_rgb(hue)
|
||||
g = int(g * brightness) & 0xFF
|
||||
r = int(r * brightness) & 0xFF
|
||||
b = int(b * brightness) & 0xFF
|
||||
o = i * 3
|
||||
double_buf[o] = g
|
||||
double_buf[o + 1] = r
|
||||
double_buf[o + 2] = b
|
||||
strip_len = num_leds * 3
|
||||
return (double_buf, strip_len)
|
||||
|
||||
|
||||
def show_rainbow(strip, double_buf, strip_len, head):
|
||||
"""DMA reads directly from double_buf at head; no copy. head in 0..strip_len-1."""
|
||||
strip.show(double_buf, head)
|
||||
|
||||
|
||||
# --- Strips + rainbow buffers per strip ---
|
||||
|
||||
strips = []
|
||||
pins = ((2, 291),
|
||||
(3, 290),
|
||||
(4, 283),
|
||||
(7, 278),
|
||||
(0, 275),
|
||||
(28, 278),
|
||||
(29, 283),
|
||||
(6, 290))
|
||||
sm = 0
|
||||
for pin, num_leds in pins:
|
||||
print(pin, num_leds)
|
||||
ws = WS2812B(num_leds, pin, sm, brightness=1.0) # 1.0 so fill() is visible
|
||||
strips.append(ws)
|
||||
sm += 1
|
||||
|
||||
# One rainbow double buffer per strip (num_leds can differ); no transfer buffer
|
||||
now = time.ticks_ms()
|
||||
rainbow_data = [make_rainbow_double(ws.num_leds, ws.brightness) for ws in strips]
|
||||
# Cumulative LEDs before each strip so rainbow lines up around the ring
|
||||
cumulative_leds = [0]
|
||||
for ws in strips[:-1]:
|
||||
cumulative_leds.append(cumulative_leds[-1] + ws.num_leds)
|
||||
# Global phase (bytes); each strip gets head = (phase + cumulative_leds * 3) % strip_len
|
||||
total_ring_leds = cumulative_leds[-1] + strips[-1].num_leds
|
||||
bytes_per_cycle = total_ring_leds * 3
|
||||
print(time.ticks_diff(time.ticks_ms(), now), "ms")
|
||||
rainbow_head = 0
|
||||
step = 3
|
||||
|
||||
while True:
|
||||
now = time.ticks_ms()
|
||||
for i, (strip, (double_buf, strip_len)) in enumerate(zip(strips, rainbow_data)):
|
||||
head = (rainbow_head + cumulative_leds[i] * 3) % strip_len
|
||||
show_rainbow(strip, double_buf, strip_len, head)
|
||||
rainbow_head = (rainbow_head + step) % bytes_per_cycle
|
||||
#print(time.ticks_diff(time.ticks_ms(), now), "ms")
|
||||
time.sleep_ms(10)
|
||||
Reference in New Issue
Block a user