class DoubleCircle: def __init__(self, driver): self.driver = driver def run(self, preset): """ DoubleCircle: symmetric band around a center index on the logical ring. - n1: center index on the logical ring (0-based, on reference strip 0) - n2: radius of the band (max distance from center) - n3: direction mode 0 → LEDs start ALL OFF and turn ON n4 LEDs at a time outward from n1 toward n1±n2 1 → LEDs start ALL ON within radius n2 and turn OFF n4 LEDs at a time inward toward n1 - n4: step size in LEDs per update - c[0]: base color used for the band """ num_leds = self.driver.num_leds if num_leds <= 0: while True: yield colors = preset.c or [] base1 = colors[0] if len(colors) >= 1 else (255, 255, 255) off = (0, 0, 0) # Apply preset/global brightness color_on = self.driver.apply_brightness(base1, preset.b) color_off = off # Center index and radius from preset; clamp center to ring length center = int(getattr(preset, "n1", 0)) % num_leds radius = max(1, int(getattr(preset, "n2", 0)) or 1) mode = int(getattr(preset, "n3", 0) or 0) # 0 = grow band outward, 1 = shrink band inward step_size = max(1, int(getattr(preset, "n4", 1)) or 1) num_strips = len(self.driver.strips) # Current "front" of the band, as a distance from center # mode 0: grow band outward (0 → radius) # mode 1: shrink band inward (radius → 0) if mode == 0: current = 0 else: current = radius while True: # Draw current frame based on current radius for i in range(num_leds): # Shortest circular distance from i to center forward = (i - center) % num_leds backward = (center - i) % num_leds dist = forward if forward < backward else backward if dist > radius: c = color_off else: if mode == 0: # Grow outward: lit if within current radius c = color_on if dist <= current else color_off else: # Shrink inward: lit if within current radius (band contracts toward center) c = color_on if dist <= current else color_off for strip_idx in range(num_strips): self.driver.set(strip_idx, i, c) self.driver.show_all() # Update current radius for next frame if mode == 0: if current >= radius: # Finished growing; hold final frame while True: yield current = min(radius, current + step_size) else: if current <= 0: # Finished shrinking; hold final frame while True: yield current = max(0, current - step_size) yield