Files
led-driver/src/patterns/pulse.py

69 lines
2.6 KiB
Python

import utime
class Pulse:
def __init__(self, driver):
self.driver = driver
def run(self, preset):
# Get colors from preset
colors = preset.c
if not colors:
colors = [(255, 255, 255)]
bg_base = preset.background_or(colors)
self.driver.fill(self.driver.apply_brightness(bg_base, preset.b))
manual = not preset.a
color_index = self.driver.step % max(1, len(colors))
cycle_start = utime.ticks_ms()
# State machine based pulse using a single generator loop
while True:
bg_color = self.driver.apply_brightness(bg_base, preset.b)
# Read current timing parameters from preset
attack_ms = max(0, int(preset.n1)) # Attack time in ms
hold_ms = max(0, int(preset.n2)) # Hold time in ms
decay_ms = max(0, int(preset.n3)) # Decay time in ms
delay_ms = 0 if manual else max(0, int(preset.d))
total_ms = attack_ms + hold_ms + decay_ms + delay_ms
if total_ms <= 0:
total_ms = 1
now = utime.ticks_ms()
elapsed = utime.ticks_diff(now, cycle_start)
base_color = colors[color_index % len(colors)]
if elapsed < attack_ms and attack_ms > 0:
# Attack: fade 0 -> 1
factor = elapsed / attack_ms
color = tuple(int(c * factor) for c in base_color)
self.driver.fill(self.driver.apply_brightness(color, preset.b))
elif elapsed < attack_ms + hold_ms:
# Hold: full brightness
self.driver.fill(self.driver.apply_brightness(base_color, preset.b))
elif elapsed < attack_ms + hold_ms + decay_ms and decay_ms > 0:
# Decay: fade 1 -> 0
dec_elapsed = elapsed - attack_ms - hold_ms
factor = max(0.0, 1.0 - (dec_elapsed / decay_ms))
color = tuple(int(c * factor) for c in base_color)
self.driver.fill(self.driver.apply_brightness(color, preset.b))
elif elapsed < total_ms:
# Delay phase: LEDs off between pulses
self.driver.fill(bg_color)
else:
# End of cycle: advance colour for the next run, then loop or stop.
nclr = max(1, len(colors))
color_index = (color_index + 1) % nclr
self.driver.step = color_index
if manual:
self.driver.fill(bg_color)
break
cycle_start = now
yield
continue
# Yield once per tick
yield