diff --git a/src/patterns.py b/src/patterns.py index 1567306..087b210 100644 --- a/src/patterns.py +++ b/src/patterns.py @@ -37,6 +37,7 @@ class Patterns(PatternsBase): "rainbow": self.rainbow, "pulse": self.pulse, "transition": self.transition, + "n_chase": self.n_chase, } @@ -78,7 +79,7 @@ class Patterns(PatternsBase): return # Auto is True: run continuously - sleep_ms = max(1, int(self.delay / 5)) + sleep_ms = max(1, int(self.delay)) last_update = utime.ticks_ms() while self.running: @@ -100,10 +101,10 @@ class Patterns(PatternsBase): self.running = True self.off() - # Get timing parameters with defaults if not set - attack_ms = getattr(self, 'n1', 200) # Attack time in ms - hold_ms = getattr(self, 'n2', 200) # Hold time in ms - decay_ms = getattr(self, 'n3', 200) # Decay time in ms + # Get timing parameters, ensure non-negative + attack_ms = max(0, int(self.n1)) # Attack time in ms + hold_ms = max(0, int(self.n2)) # Hold time in ms + decay_ms = max(0, int(self.n3)) # Decay time in ms # Ensure we have at least one color if not self.colors: @@ -269,5 +270,71 @@ class Patterns(PatternsBase): # Move to next color color_index = (color_index + 1) % len(self.colors) + self.running = False + self.stopped = True + + def n_chase(self): + """N-chase pattern: n1 LEDs of color0, n2 LEDs of color1, repeating. + Moves by n3 on even steps, n4 on odd steps (n3/n4 can be positive or negative)""" + self.stopped = False + self.running = True + + if len(self.colors) < 2: + # Need at least 2 colors + self.running = False + self.stopped = True + return + + n1 = max(1, int(self.n1)) # LEDs of color 0 + n2 = max(1, int(self.n2)) # LEDs of color 1 + n3 = int(self.n3) # Step movement on odd steps (can be negative) + n4 = int(self.n4) # Step movement on even steps (can be negative) + + segment_length = n1 + n2 + position = 0 # Current position offset + step_count = 0 # Track which step we're on + + color0 = self.apply_brightness(self.colors[0]) + color1 = self.apply_brightness(self.colors[1]) + + transition_duration = max(10, self.delay) + last_update = utime.ticks_ms() + + while self.running: + current_time = utime.ticks_ms() + if utime.ticks_diff(current_time, last_update) >= transition_duration: + # Clear all LEDs + self.n.fill((0, 0, 0)) + + # Draw repeating pattern starting at position + for i in range(self.num_leds): + # Calculate position in the repeating segment + relative_pos = (i - position) % segment_length + if relative_pos < 0: + relative_pos = (relative_pos + segment_length) % segment_length + + # Determine which color based on position in segment + if relative_pos < n1: + self.n[i] = color0 + else: + self.n[i] = color1 + + self.n.write() + + # Move position by n3 or n4 on alternate steps + if step_count % 2 == 0: + position = position + n3 + else: + position = position + n4 + + # Wrap position to keep it reasonable + max_pos = self.num_leds + segment_length + position = position % max_pos + if position < 0: + position += max_pos + + step_count += 1 + last_update = current_time + self.running = False self.stopped = True \ No newline at end of file