63 lines
2.2 KiB
Python
63 lines
2.2 KiB
Python
import utime
|
|
|
|
|
|
class Icicles:
|
|
"""Icicles hanging from anchor points; tips brighten toward max length then shrink."""
|
|
|
|
def __init__(self, driver):
|
|
self.driver = driver
|
|
|
|
def run(self, preset):
|
|
colors = preset.c if preset.c else [(240, 248, 255), (160, 210, 255), (255, 255, 255)]
|
|
spacing = max(1, int(preset.n1) if int(preset.n1) > 0 else 12)
|
|
nled = self.driver.num_leds
|
|
max_len = max(
|
|
2,
|
|
min(
|
|
int(preset.n2) if int(preset.n2) > 0 else min(14, max(3, nled // 4)),
|
|
max(2, nled),
|
|
),
|
|
)
|
|
span = max_len * 2
|
|
phase_step = max(1, int(preset.n3) if int(preset.n3) > 0 else 1)
|
|
phase = 0
|
|
last = utime.ticks_ms()
|
|
|
|
while True:
|
|
d_ms = max(1, int(preset.d))
|
|
now = utime.ticks_ms()
|
|
if utime.ticks_diff(now, last) >= d_ms:
|
|
bg_rgb = preset.background_or(colors)
|
|
bg = self.driver.apply_brightness(bg_rgb, preset.b)
|
|
|
|
for i in range(nled):
|
|
self.driver.n[i] = bg
|
|
|
|
aidx = 0
|
|
for anchor in range(0, nled, spacing):
|
|
tri_i = (phase + aidx * 5) % span
|
|
ic_len = tri_i if tri_i <= max_len else span - tri_i
|
|
tip_c = colors[aidx % len(colors)]
|
|
tip = self.driver.apply_brightness(tip_c, preset.b)
|
|
for k in range(ic_len):
|
|
idx = anchor + k
|
|
if idx >= nled:
|
|
break
|
|
br = ((k + 1) * 255) // max(1, ic_len)
|
|
self.driver.n[idx] = (
|
|
(tip[0] * br + bg[0] * (255 - br)) // 255,
|
|
(tip[1] * br + bg[1] * (255 - br)) // 255,
|
|
(tip[2] * br + bg[2] * (255 - br)) // 255,
|
|
)
|
|
aidx += 1
|
|
|
|
self.driver.n.write()
|
|
phase = (phase + phase_step) % span
|
|
last = utime.ticks_add(last, d_ms)
|
|
|
|
if not preset.a:
|
|
yield
|
|
return
|
|
|
|
yield
|