"""Spin: continues from Grab — segment (10 each side of center) moves slowly up to the top. Preset color, n1 = rate.""" import utime SPAN = 0 # LEDs on each side of center (match Grab) LUT_SIZE = 256 # gradient lookup table entries class Spin: def __init__(self, driver): self.driver = driver def run(self, preset): strips = self.driver.strips self.driver.fill((0, 0, 0)) self.driver.show_all() active_indices = (0, 4) c0 = preset.c[0] c1 = preset.c[1] # Precompute gradient LUT: t in [0,1] maps to (r,g,b) lut = [] for k in range(LUT_SIZE): t = k / (LUT_SIZE - 1) if LUT_SIZE > 1 else 1 r = int(c0[0] + (c1[0] - c0[0]) * t) g = int(c0[1] + (c1[1] - c0[1]) * t) b = int(c0[2] + (c1[2] - c0[2]) * t) lut.append((r, g, b)) # For each active strip we expand from just outside the grab center # left: from (mid - SPAN) down to 0 # right: from (mid + SPAN) up to end midpoints = self.driver.strip_midpoints rate = max(1, int(preset.n1) or 1) delay_ms = max(1, int(preset.d) or 1) margin = max(0, int(preset.n2) or 0) # Track current extents of each arm left = {} right = {} for idx in active_indices: if 0 <= idx < len(strips): mid = midpoints[idx] left[idx] = mid - SPAN # inner edge of left arm right[idx] = mid + SPAN + 1 # inner edge of right arm last_update = utime.ticks_ms() while True: now = utime.ticks_ms() if utime.ticks_diff(now, last_update) < delay_ms: yield continue last_update = now for idx in active_indices: if idx < 0 or idx >= len(strips): continue strip = strips[idx] n = strip.num_leds mid = midpoints[idx] # Expand arms at the same rate on both sides step = max(1, rate) new_left = max(margin, left[idx] - step) new_right = min(n - margin, right[idx] + step) # Left arm: c1 at outer, c0 at inner. Right arm: c0 at inner, c1 at outer. left_len = max(0, (mid - SPAN) - new_left) right_len = max(0, new_right - (mid + SPAN + 1)) bright = strip.brightness ar = strip.ar for j, i in enumerate(range(new_left, mid - SPAN)): if 0 <= i < n: t = 1 - j / (left_len - 1) if left_len > 1 else 0 lut_idx = min(int(t * (LUT_SIZE - 1)), LUT_SIZE - 1) r, g, b = lut[lut_idx] base = i * 3 ar[base] = int(g * bright) ar[base + 1] = int(r * bright) ar[base + 2] = int(b * bright) for j, i in enumerate(range(mid + SPAN + 1, new_right)): if 0 <= i < n: t = j / (right_len - 1) if right_len > 1 else 0 lut_idx = min(int(t * (LUT_SIZE - 1)), LUT_SIZE - 1) r, g, b = lut[lut_idx] base = i * 3 ar[base] = int(g * bright) ar[base + 1] = int(r * bright) ar[base + 2] = int(b * bright) left[idx] = new_left right[idx] = new_right # Show only on this strip strip.show() yield