# Standalone MicroPython Voice Animation: Waiting Orbit # Exposes run(text="", frames=...) and runs automatically if executed directly. import time import math try: import board_config display = getattr(board_config, 'display_instance', None) except Exception: board_config = None display = None def draw_center_text(d, msg, y, w, scale=1, c=1): char_w = 8 * scale x = max(0, (w - len(msg) * char_w) // 2) if hasattr(d, 'text_large') and scale > 1: try: d.text_large(msg, x, y, scale, c) return except Exception: pass d.text(msg, x, y, c) def run(text="", frames=100): if not display: print("board_config.display_instance is not available. Skipping animation.") return width = getattr(display, 'width', 400) height = getattr(display, 'height', 300) cx, cy = width // 2, height // 2 label = text if text else "THINKING..." frame = 0 try: while True: if frames is not None and frames > 0 and frame >= frames: break display.clear(0) # Draw central pulsing core # Uses sin wave to expand/contract pulse = int(14 + 4 * math.sin(frame * 0.18)) display.rect(cx - pulse, cy - pulse, pulse * 2, pulse * 2, 1) display.rect(cx - pulse + 3, cy - pulse + 3, (pulse - 3) * 2, (pulse - 3) * 2, 1) display.fill_rect(cx - 3, cy - 3, 6, 6, 1) # Draw a dotted circular path of radius 60 for a_deg in range(0, 360, 15): angle = math.radians(a_deg) px = cx + int(60 * math.cos(angle)) py = cy + int(60 * math.sin(angle)) display.fill_rect(px, py, 2, 2, 1) # Draw 4 orbiting ring nodes for node_idx in range(4): angle = (frame * 0.08) + (node_idx * math.pi / 2) nx = cx + int(60 * math.cos(angle)) ny = cy + int(60 * math.sin(angle)) # Draw square ring nodes display.fill_rect(nx - 6, ny - 6, 12, 12, 1) display.fill_rect(nx - 4, ny - 4, 8, 8, 0) # Draw centered text label at the bottom draw_center_text(display, label, height - 35, width, scale=1, c=1) display.show() frame += 1 try: time.sleep_ms(50) except AttributeError: time.sleep(0.05) except KeyboardInterrupt: print("Animation interrupted by user.") if __name__ in ('__main__', '__name__'): run()