patterns: centralize timing in tick(); remove selected-delay coupling; update self-test to use per-config durations
This commit is contained in:
@@ -13,6 +13,7 @@ class PatternBase:
|
||||
self.brightness = brightness
|
||||
self.patterns = {}
|
||||
self.selected = selected
|
||||
self.run = True
|
||||
# Ensure colors list always starts with at least two for robust transition handling
|
||||
self.colors = [color1, color2] if color1 != color2 else [color1, (255, 255, 255)] # Fallback if initial colors are same
|
||||
if not self.colors: # Ensure at least one color exists
|
||||
@@ -26,10 +27,12 @@ class PatternBase:
|
||||
|
||||
self.hold_start_time = utime.ticks_ms() # Time when the current color hold started
|
||||
|
||||
# New attributes for scanner patterns
|
||||
# New attributes for scanner patterns (moved from Patterns to PatternBase as they are generic enough)
|
||||
self.scanner_direction = 1 # 1 for forward, -1 for backward
|
||||
self.scanner_tail_length = 3 # Number of trailing pixels
|
||||
|
||||
# Removed: selected_delay caching
|
||||
|
||||
def sync(self):
|
||||
self.pattern_step=0
|
||||
self.last_update = utime.ticks_ms() - self.delay
|
||||
@@ -40,14 +43,32 @@ class PatternBase:
|
||||
self.hold_start_time = utime.ticks_ms() # Reset hold time
|
||||
# Reset scanner specific variables
|
||||
self.scanner_direction = 1
|
||||
self.tick()
|
||||
# self.tick() # Tick moved to Patterns, as patterns dict is there
|
||||
|
||||
def set_pattern_step(self, step):
|
||||
self.pattern_step = step
|
||||
|
||||
def tick(self):
|
||||
if self.patterns[self.selected]:
|
||||
if self.patterns.get(self.selected) and self.run:
|
||||
# Compute gating interval per pattern based on current delay
|
||||
interval = None
|
||||
if self.selected in ("color_wipe", "theater_chase", "blink", "scanner", "fill_range", "n_chase", "alternating"):
|
||||
interval = self.delay
|
||||
elif self.selected == "rainbow_cycle":
|
||||
interval = max(1, int(self.delay // 5))
|
||||
elif self.selected == "flicker":
|
||||
interval = max(1, int(self.delay // 5))
|
||||
elif self.selected == "bidirectional_scanner":
|
||||
interval = max(1, int(self.delay // 100))
|
||||
# Patterns intentionally not gated here: off, on, external, pulse, color_transition
|
||||
|
||||
if interval is not None:
|
||||
current_time = utime.ticks_ms()
|
||||
if utime.ticks_diff(current_time, self.last_update) < interval:
|
||||
return interval
|
||||
self.patterns[self.selected]()
|
||||
return interval
|
||||
return None
|
||||
|
||||
def update_num_leds(self, pin, num_leds):
|
||||
self.n = NeoPixel(Pin(pin, Pin.OUT), num_leds)
|
||||
@@ -59,6 +80,7 @@ class PatternBase:
|
||||
# Update transition duration and hold duration when delay changes
|
||||
self.transition_duration = self.delay * 50
|
||||
self.hold_duration = self.delay * 10
|
||||
# No cached interval
|
||||
|
||||
|
||||
def set_brightness(self, brightness):
|
||||
@@ -157,6 +179,7 @@ class PatternBase:
|
||||
return tuple(int(c * effective_brightness / 255) for c in color)
|
||||
|
||||
def select(self, pattern):
|
||||
# Removed self.run = True here. It should be handled by Patterns class.
|
||||
if pattern in self.patterns:
|
||||
self.selected = pattern
|
||||
self.sync() # Reset pattern state when selecting a new pattern
|
||||
|
Reference in New Issue
Block a user