diff --git a/src/patterns/bar_graph.py b/src/patterns/bar_graph.py index 72738d2..bb6db52 100644 --- a/src/patterns/bar_graph.py +++ b/src/patterns/bar_graph.py @@ -7,15 +7,23 @@ class BarGraph: def run(self, preset): colors = preset.c if preset.c else [(0, 255, 0), (255, 80, 0)] - level = max(0, min(100, int(preset.n1) if int(preset.n1) >= 0 else 50)) - target = (self.driver.num_leds * level) // 100 - lit = self.driver.apply_brightness(colors[0], preset.b) - unlit = self.driver.apply_brightness(colors[1] if len(colors) > 1 else (0, 0, 0), preset.b) + last_update = utime.ticks_ms() while True: - for i in range(self.driver.num_leds): - self.driver.n[i] = lit if i < target else unlit - self.driver.n.write() + delay_ms = max(1, int(preset.d)) + now = utime.ticks_ms() + if utime.ticks_diff(now, last_update) >= delay_ms: + level = max(0, min(100, int(preset.n1) if int(preset.n1) >= 0 else 50)) + target = (self.driver.num_leds * level) // 100 + lit = self.driver.apply_brightness(colors[0], preset.b) + unlit = self.driver.apply_brightness( + colors[1] if len(colors) > 1 else (0, 0, 0), + preset.b, + ) + for i in range(self.driver.num_leds): + self.driver.n[i] = lit if i < target else unlit + self.driver.n.write() + last_update = utime.ticks_add(last_update, delay_ms) + if not preset.a: + yield + return yield - if not preset.a: - return - utime.sleep_ms(max(1, int(preset.d))) diff --git a/src/patterns/heartbeat.py b/src/patterns/heartbeat.py index 37b4819..c14b4e4 100644 --- a/src/patterns/heartbeat.py +++ b/src/patterns/heartbeat.py @@ -7,19 +7,24 @@ class Heartbeat: def run(self, preset): colors = preset.c if preset.c else [(255, 0, 40)] - p1 = max(20, int(preset.n1) if int(preset.n1) > 0 else 120) - p2 = max(20, int(preset.n2) if int(preset.n2) > 0 else 80) - pause = max(20, int(preset.n3) if int(preset.n3) > 0 else 500) + phase = 0 + phase_start = utime.ticks_ms() + lit_color = self.driver.apply_brightness(colors[0], preset.b) while True: - c = self.driver.apply_brightness(colors[0], preset.b) - self.driver.fill(c) - utime.sleep_ms(p1) - self.driver.fill((0, 0, 0)) - utime.sleep_ms(max(20, int(preset.d))) - self.driver.fill(c) - utime.sleep_ms(p2) - self.driver.fill((0, 0, 0)) - utime.sleep_ms(pause) + p1 = max(20, int(preset.n1) if int(preset.n1) > 0 else 120) + p2 = max(20, int(preset.n2) if int(preset.n2) > 0 else 80) + pause = max(20, int(preset.n3) if int(preset.n3) > 0 else 500) + beat_gap = max(20, int(preset.d)) + lit_color = self.driver.apply_brightness(colors[0], preset.b) + phase_durations = (p1, beat_gap, p2, pause) + phase_colors = (lit_color, (0, 0, 0), lit_color, (0, 0, 0)) + + now = utime.ticks_ms() + if utime.ticks_diff(now, phase_start) >= phase_durations[phase]: + phase = (phase + 1) % 4 + phase_start = utime.ticks_add(phase_start, phase_durations[(phase - 1) % 4]) + + self.driver.fill(phase_colors[phase]) yield - if not preset.a: + if not preset.a and phase == 0: return diff --git a/src/patterns/palette_morph.py b/src/patterns/palette_morph.py index 72ccd91..27fb35f 100644 --- a/src/patterns/palette_morph.py +++ b/src/patterns/palette_morph.py @@ -34,9 +34,15 @@ class PaletteMorph: base_idx = 0 start = utime.ticks_ms() phase = self.driver.step % 256 + last_update = start while True: now = utime.ticks_ms() + delay_ms = max(1, int(preset.d)) + if utime.ticks_diff(now, last_update) < delay_ms: + yield + continue + last_update = utime.ticks_add(last_update, delay_ms) age = utime.ticks_diff(now, start) if age < morph: t = (age * 255) // morph @@ -72,5 +78,4 @@ class PaletteMorph: return phase = (phase + warp_rate) & 255 self.driver.step = phase - utime.sleep_ms(max(1, int(preset.d))) yield diff --git a/src/patterns/strobe_burst.py b/src/patterns/strobe_burst.py index 91d57cb..aaafc9c 100644 --- a/src/patterns/strobe_burst.py +++ b/src/patterns/strobe_burst.py @@ -7,18 +7,38 @@ class StrobeBurst: def run(self, preset): colors = preset.c if preset.c else [(255, 255, 255)] - count = max(1, int(preset.n1) if int(preset.n1) > 0 else 3) - gap = max(1, int(preset.n2) if int(preset.n2) > 0 else 60) - cooldown = max(1, int(preset.n3) if int(preset.n3) > 0 else 400) - c = self.driver.apply_brightness(colors[0], preset.b) + state = "flash_on" + flash_idx = 0 + state_start = utime.ticks_ms() while True: - for _ in range(count): + count = max(1, int(preset.n1) if int(preset.n1) > 0 else 3) + gap = max(1, int(preset.n2) if int(preset.n2) > 0 else 60) + cooldown = max(1, int(preset.n3) if int(preset.n3) > 0 else 400) + on_ms = max(1, int(preset.d) // 2) + c = self.driver.apply_brightness(colors[0], preset.b) + now = utime.ticks_ms() + + if state == "flash_on": self.driver.fill(c) - utime.sleep_ms(max(1, int(preset.d)//2)) + if utime.ticks_diff(now, state_start) >= on_ms: + state = "flash_off" + state_start = utime.ticks_add(state_start, on_ms) + elif state == "flash_off": self.driver.fill((0, 0, 0)) - utime.sleep_ms(gap) - yield - utime.sleep_ms(cooldown) + if utime.ticks_diff(now, state_start) >= gap: + flash_idx += 1 + if flash_idx >= count: + if not preset.a: + return + state = "cooldown" + flash_idx = 0 + state_start = utime.ticks_add(state_start, gap) + else: + state = "flash_on" + state_start = utime.ticks_add(state_start, gap) + else: + self.driver.fill((0, 0, 0)) + if utime.ticks_diff(now, state_start) >= cooldown: + state = "flash_on" + state_start = utime.ticks_add(state_start, cooldown) yield - if not preset.a: - return