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