import utime class GradientScroll: def __init__(self, driver): self.driver = driver def _render(self, colors, phase, brightness): num_leds = self.driver.num_leds color_count = len(colors) if num_leds <= 0 or color_count <= 0: return if color_count == 1: self.driver.fill(self.driver.apply_brightness(colors[0], brightness)) return full_span = color_count * 256 phase_shift = (phase * full_span) // 256 for i in range(num_leds): pos = ((i * full_span) // num_leds + phase_shift) % full_span idx = pos // 256 frac = pos & 255 c1 = colors[idx] c2 = colors[(idx + 1) % color_count] blended = ( c1[0] + ((c2[0] - c1[0]) * frac) // 256, c1[1] + ((c2[1] - c1[1]) * frac) // 256, c1[2] + ((c2[2] - c1[2]) * frac) // 256, ) self.driver.n[i] = self.driver.apply_brightness(blended, brightness) self.driver.n.write() def run(self, preset): """Scrolling blended gradient. n1: phase step amount (default 1) """ colors = preset.c if preset.c else [(255, 0, 0), (0, 0, 255)] phase = self.driver.step % 256 step_amount = max(1, int(preset.n1) if int(preset.n1) > 0 else 1) last_update = utime.ticks_ms() while True: delay_ms = max(1, int(preset.d)) now = utime.ticks_ms() if utime.ticks_diff(now, last_update) >= delay_ms: self._render(colors, phase, preset.b) phase = (phase + step_amount) % 256 self.driver.step = phase last_update = utime.ticks_add(last_update, delay_ms) if not preset.a: yield return yield