import machine
import st7789
import math
import time

# ── SPI & Display setup ──────────────────────────────────────────
spi = machine.SPI(0,
    baudrate=40_000_000,
    polarity=1,
    phase=1,
    sck=machine.Pin(2),
    mosi=machine.Pin(3))

tft = st7789.ST7789(spi, 240, 320,
    reset=machine.Pin(27, machine.Pin.OUT),
    dc=machine.Pin(29, machine.Pin.OUT),
    cs=machine.Pin(28, machine.Pin.OUT),
    xstart=0, ystart=0)

tft.init()

# ── Colors ───────────────────────────────────────────────────────
BLACK  = st7789.color565(0,   0,   0)
WHITE  = st7789.color565(255, 255, 255)
RED    = st7789.color565(255, 0,   0)
GREEN  = st7789.color565(0,   255, 0)
BLUE   = st7789.color565(0,   0,   255)
CYAN   = st7789.color565(0,   255, 255)
YELLOW = st7789.color565(255, 255, 0)
PURPLE = st7789.color565(180, 0,   255)
ORANGE = st7789.color565(255, 140, 0)

W, H = 240, 320
CX, CY = W // 2, H // 2

# ── Helper: draw a filled circle ─────────────────────────────────
def fill_circle(x0, y0, r, color):
    for y in range(-r, r + 1):
        dx = int(math.sqrt(r * r - y * y))
        tft.hline(x0 - dx, y0 + y, 2 * dx, color)

# ── Helper: draw a polygon ────────────────────────────────────────
def polygon(cx, cy, r, sides, color, angle_offset=0):
    pts = []
    for i in range(sides):
        a = math.radians(angle_offset + i * 360 / sides)
        pts.append((int(cx + r * math.sin(a)), int(cy - r * math.cos(a))))
    for i in range(sides):
        x0, y0 = pts[i]
        x1, y1 = pts[(i + 1) % sides]
        tft.line(x0, y0, x1, y1, color)

# ══════════════════════════════════════════════════════════════════
# PATTERNS
# ══════════════════════════════════════════════════════════════════

def pattern_concentric_circles():
    tft.fill(BLACK)
    colors = [RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, PURPLE]
    for i, c in enumerate(colors):
        r = 20 + i * 22
        fill_circle(CX, CY, r, c)
    fill_circle(CX, CY, 18, BLACK)

def pattern_grid():
    tft.fill(BLACK)
    step = 30
    for x in range(0, W, step):
        tft.vline(x, 0, H, CYAN)
    for y in range(0, H, step):
        tft.hline(0, y, W, CYAN)
    for x in range(0, W, step):
        for y in range(0, H, step):
            fill_circle(x, y, 4, YELLOW)

def pattern_nested_polygons():
    tft.fill(BLACK)
    shapes = [(3, RED), (4, GREEN), (5, CYAN), (6, YELLOW), (7, PURPLE), (8, ORANGE)]
    for i, (sides, color) in enumerate(shapes):
        polygon(CX, CY, 20 + i * 24, sides, color, angle_offset=i * 15)

def pattern_star_burst():
    tft.fill(BLACK)
    colors = [RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE]
    num_lines = 36
    for i in range(num_lines):
        a = math.radians(i * (360 / num_lines))
        x1 = int(CX + 10 * math.cos(a))
        y1 = int(CY + 10 * math.sin(a))
        x2 = int(CX + 150 * math.cos(a))
        y2 = int(CY + 150 * math.sin(a))
        tft.line(x1, y1, x2, y2, colors[i % len(colors)])

def pattern_diamond_grid():
    tft.fill(BLACK)
    size = 28
    for row in range(-1, H // size + 2):
        for col in range(-1, W // size + 2):
            cx = col * size + (size // 2 if row % 2 else 0)
            cy = row * size
            color = [RED, BLUE, GREEN, PURPLE][(row + col) % 4]
            pts = [
                (cx,             cy - size // 2),
                (cx + size // 2, cy),
                (cx,             cy + size // 2),
                (cx - size // 2, cy),
            ]
            for i in range(4):
                x0, y0 = pts[i]
                x1, y1 = pts[(i + 1) % 4]
                tft.line(x0, y0, x1, y1, color)

def pattern_spiral():
    tft.fill(BLACK)
    colors = [RED, ORANGE, YELLOW, GREEN, CYAN, BLUE, PURPLE]
    steps = 400
    for i in range(steps):
        a = math.radians(i * 8)
        r = i * 0.38
        x = int(CX + r * math.cos(a))
        y = int(CY + r * math.sin(a))
        if 0 <= x < W and 0 <= y < H:
            tft.pixel(x, y, colors[i % len(colors)])
            tft.pixel(x+1, y, colors[i % len(colors)])

def pattern_checkerboard():
    tft.fill(BLACK)
    size = 30
    colors_a = [RED, BLUE]
    colors_b = [YELLOW, GREEN]
    for row in range(H // size + 1):
        for col in range(W // size + 1):
            c = colors_a[(row + col) % 2] if row % 2 == 0 else colors_b[(row + col) % 2]
            x = col * size
            y = row * size
            for dy in range(size):
                if y + dy < H:
                    tft.hline(x, y + dy, min(size, W - x), c)

# ── Pattern list ─────────────────────────────────────────────────
PATTERNS = [
    ("Concentric Circles",  pattern_concentric_circles),
    ("Grid",                pattern_grid),
    ("Nested Polygons",     pattern_nested_polygons),
    ("Star Burst",          pattern_star_burst),
    ("Diamond Grid",        pattern_diamond_grid),
    ("Spiral",              pattern_spiral),
    ("Checkerboard",        pattern_checkerboard),
]

# ── Main loop ────────────────────────────────────────────────────
current = 0

while True:
    PATTERNS[current][1]()
    time.sleep(5)
    current = (current + 1) % len(PATTERNS)