73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
import random
|
|
import utime
|
|
|
|
|
|
class Rime:
|
|
"""Slow frost build-up on a chilly background — gentle random brightening then decay."""
|
|
|
|
def __init__(self, driver):
|
|
self.driver = driver
|
|
|
|
def run(self, preset):
|
|
colors = preset.c if preset.c else [(220, 235, 255), (255, 255, 255), (185, 220, 255)]
|
|
num = self.driver.num_leds
|
|
if num <= 0:
|
|
while True:
|
|
yield
|
|
return
|
|
|
|
# n1: spawn tendency (like twinkle upper range)
|
|
chill = max(1, min(255, int(preset.n1) if int(preset.n1) > 0 else 36))
|
|
# n2: decay per refresh (subtract from glow buffer)
|
|
melt = max(1, min(255, int(preset.n2) if int(preset.n2) > 0 else 12))
|
|
# n3: how many LEDs can flash brighter per refresh (cap)
|
|
spark_cap = max(1, min(num, int(preset.n3) if int(preset.n3) > 0 else 3))
|
|
|
|
glow = [0] * num
|
|
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:
|
|
base_bg = preset.background_or(colors)
|
|
bg = self.driver.apply_brightness(base_bg, preset.b)
|
|
|
|
for i in range(num):
|
|
if glow[i] > melt:
|
|
glow[i] -= melt
|
|
else:
|
|
glow[i] = 0
|
|
|
|
spawned = 0
|
|
tries = spark_cap + num // 8
|
|
for _ in range(tries):
|
|
if spawned >= spark_cap:
|
|
break
|
|
if random.randint(0, 255) >= chill:
|
|
continue
|
|
j = random.randint(0, num - 1)
|
|
glow[j] = min(255, glow[j] + random.randint(80, 200))
|
|
spawned += 1
|
|
|
|
palette = colors
|
|
for i in range(num):
|
|
g = glow[i]
|
|
fg = palette[i % len(palette)]
|
|
hi = self.driver.apply_brightness(fg, preset.b)
|
|
mix = max(0, min(255, g))
|
|
self.driver.n[i] = (
|
|
(hi[0] * mix + bg[0] * (255 - mix)) // 255,
|
|
(hi[1] * mix + bg[1] * (255 - mix)) // 255,
|
|
(hi[2] * mix + bg[2] * (255 - mix)) // 255,
|
|
)
|
|
|
|
self.driver.n.write()
|
|
last = utime.ticks_add(last, d_ms)
|
|
|
|
if not preset.a:
|
|
yield
|
|
return
|
|
|
|
yield
|