#6x6 matrix panel

#green to pin 1 - GP0
#Red to 3v3 (out)
#Brown to Ground

#Pin2 - GP1
import machine
import time
from neopixel import Neopixel
import random

#constants
numpix = 36 #number of pixels
pin = 0
pixels = Neopixel(numpix, 0, pin, "GRB")
button = machine.Pin(1,machine.Pin.IN, machine.Pin.PULL_UP)
led_onboard = machine.Pin(25,machine.Pin.OUT)

#variables
np = 0 #next pattern
spd = 0.1 #speed
psh = False #button pushed

#colours
yellow = (255, 255, 0)
orange = (255, 70, 0)
lime = (0, 255, 0)
olive = (128,128,0)
blue = (0, 0, 255)
red = (255, 0, 0)
white = (255,255,255)
purple = (128,0,255)
pink = (255,0,255)
cyan = (0,255,255)
off = (0,0,0)

#matrix positions
matrix = [[0, 1, 2, 3, 4, 5 ],
          [11,10,9, 8, 7, 6 ],
          [12,13,14,15,16,17],
          [23,22,21,20,19,18],
          [24,25,26,27,28,29],
          [35,34,33,32,31,30]]

spinframe = [[[0,0,1,0,0,0],
          [0,0,1,0,0,0],
          [0,0,1,1,1,1],
          [1,1,1,1,0,0],
          [0,0,0,1,0,0],
          [0,0,0,1,0,0]],

         [[0,0,0,1,0,0],
          [0,0,1,0,0,0],
          [1,0,1,1,1,0],
          [0,1,1,1,0,1],
          [0,0,0,1,0,0],
          [0,0,1,0,0,0]],
         
         [[0,0,0,0,1,0],
          [1,0,0,1,0,0],
          [0,1,1,1,0,0],
          [0,0,1,1,1,0],
          [0,0,1,0,0,1],
          [0,1,0,0,0,0]],
         
         [[1,0,0,0,0,1],
          [0,1,0,0,1,0],
          [0,0,1,1,0,0],
          [0,0,1,1,0,0],
          [0,1,0,0,1,0],
          [1,0,0,0,0,1]],
         
         [[0,1,0,0,0,0],
          [0,0,1,0,0,1],
          [0,0,1,1,1,0],
          [0,1,1,1,0,0],
          [1,0,0,1,0,0],
          [0,0,0,0,1,0]],
         
         [[0,0,0,1,0,0],
          [0,0,0,1,0,0],
          [1,1,1,1,0,0],
          [0,0,1,1,1,1],
          [0,0,1,0,0,0],
          [0,0,1,0,0,0]]
         ]

pattern = [yellow, orange, lime, olive, blue, red, white, pink, purple, cyan]
pos = 0

pixels.brightness(50)

#pattern functions

def march(c,t): # colour, delay time
    global psh
    psh = False
    for x in range(6):
        for y in range(6):
            pos = matrix[x][y]
            pixels.set_pixel(pos, c)
            pixels.show()
            time.sleep(t)
            if psh:
                return
                
def wipe(c,t): #colour, delay time
    global psh
    psh = False
    for x in range(6):
        time.sleep(t)
        for y in range(6):
            pos = matrix[x][y]
            pixels.set_pixel(pos, c)
            pixels.show()
            if psh:
                return

def corner(c,t): #colour, delay time
    global psh
    psh = False
    for z in range(6):
        pos = matrix[z][z]
        pixels.set_pixel(pos, c)
        for x in range(z):
            pos1 = matrix[z][x]
            pos2 = matrix[x][z]
            pixels.set_pixel(pos1, c)
            pixels.set_pixel(pos2, c)
        pixels.show()
        time.sleep(t)
        if psh:
            return
        
def rndpix(t): #delay time
    global psh
    psh = False
    for col in pattern:
        pos = random.randint(0,numpix-1)
        pixels.set_pixel(pos,col)
        pixels.show()
        time.sleep(t)
        if psh:
            return
        
def squares(t): #delay time
    global psh
    psh = False
    for col in pattern:
        x = random.randint(0,4)
        y = random.randint(0,4)
        pos1 = matrix[x][y]
        pos2 = matrix[x+1][y]
        pos3 = matrix[x][y+1]
        pos4 = matrix[x+1][y+1]
        pixels.set_pixel(pos1,col)
        pixels.set_pixel(pos2,col)
        pixels.set_pixel(pos3,col)
        pixels.set_pixel(pos4,col)
        pixels.show()
        time.sleep(t)
        if psh:
            return

def spiralin(c,t): #colour,delay time
    global psh
    psh = False
    l = 1
    x = 2
    y = 2
    for a in range(3):    
        #go right
        for z in range(l):
            pos = matrix[x][y]
            pixels.set_pixel(pos,c)
            pixels.show()
            time.sleep(t)
            x = x + 1
            if psh:
                return
        
        #go up
        for z in range(l):
            pos = matrix[x][y]
            pixels.set_pixel(pos,c)
            pixels.show()
            time.sleep(t)
            y = y + 1
            if psh:
                return
        
        
        #increase length
        l = l + 1
        
        #go left
        for z in range(l):
            pos = matrix[x][y]
            pixels.set_pixel(pos,c)
            pixels.show()
            time.sleep(t)
            x = x - 1
            if psh:
                return
        
        #stop at edge
        if x < 0:
            break
        
        #go down
        for z in range(l):
            pos = matrix[x][y]
            pixels.set_pixel(pos,c)
            pixels.show()
            time.sleep(t)
            y = y - 1
            if psh:
                return
        
        #increase length
        l = l + 1

def spiralout(c,t): #colour,delay time
    global psh
    psh = False
    l = 5
    x = 0
    y = 5
    for a in range(3):    
        #go down
        for z in range(l):
           pos = matrix[x][y]
           pixels.set_pixel(pos,c)
           pixels.show()
           time.sleep(t)
           y = y - 1
           if psh:
                return
        
        #decrease length
        if l < 5:
            l = l - 1
            
        #go right
        for z in range(l):
            pos = matrix[x][y]
            pixels.set_pixel(pos,c)
            pixels.show()
            time.sleep(t)
            x = x + 1
            if psh:
                return

        #go up
        for z in range(l):
            pos = matrix[x][y]
            pixels.set_pixel(pos,c)
            pixels.show()
            time.sleep(t)
            y = y + 1
            if psh:
                return
        
        #decrease length
        if l > 1:
            l = l - 1

        #go left
        for z in range(l):
            pos = matrix[x][y]
            pixels.set_pixel(pos,c)
            pixels.show()
            time.sleep(t)
            x = x - 1
            if psh:
                return

def fillin(c,t): #colour,delay time
    global psh
    psh = False
    l=6
    x=0
    y=0
    for a in range(3):
        for b in range(l):
            pos = matrix[x+b][y]
            pixels.set_pixel(pos,c)
        for b in range(l):
            pos = matrix[x][y+b]
            pixels.set_pixel(pos,c)
        for b in range(l):
            pos = matrix[x+b][y + (l-1)]
            pixels.set_pixel(pos,c)
        for b in range(l):
            pos = matrix[x + (l-1)][y+b]
            pixels.set_pixel(pos,c)
        pixels.show()
        time.sleep(t)
        l = l - 2
        x = x + 1
        y = y + 1
        if psh:
            return

def fillout(c,t): #colour,delay time
    global psh
    psh = False
    l=2
    x=2
    y=2
    for a in range(3):
        for b in range(l):
            pos = matrix[x+b][y]
            pixels.set_pixel(pos,c)
        for b in range(l):
            pos = matrix[x][y+b]
            pixels.set_pixel(pos,c)
        for b in range(l):
            pos = matrix[x+b][y + (l-1)]
            pixels.set_pixel(pos,c)
        for b in range(l):
            pos = matrix[x + (l-1)][y+b]
            pixels.set_pixel(pos,c)
        pixels.show()
        time.sleep(t)
        l = l + 2
        x = x - 1
        y = y - 1
        if psh:
            return

def spin(c,t): #animation colour, delay time
    global psh
    psh = False
    for f in range(5):
        for y in range(6):
            for x in range(6):
                pos = matrix[x][y]
                if spinframe[f][x][y] == 1:
                    pixels.set_pixel(pos,c)
                else:
                    pixels.set_pixel(pos,off)
                if psh:
                    return
        pixels.show()
        time.sleep(t)

def bounce(c,t): #colour,delay time
    global psh
    psh = False
    x = random.randint(0,5)
    y = random.randint(0,5)
    xdir = 0
    ydir = 0
    while xdir == 0 or ydir == 0:
        xdir = random.randint(-1,1)
        ydir = random.randint(-1,1)
    for f in range(20):
        pos = matrix[x][y]
        pixels.set_pixel(pos,c)
        pixels.show()
        time.sleep(t)
        pos = matrix[x][y]
        pixels.set_pixel(pos,off)
        pixels.show()

        if x == 0 and xdir == -1:
            xdir = 1
        if x == 5 and xdir == 1:
            xdir = -1
        x = x + xdir
        
        if y == 0 and ydir == -1:
            ydir = 1
        if y == 5 and ydir == 1:
            ydir = -1
        y = y + ydir
        if psh:
            return
        
def rndmove(c,t): #colour,delay time
    global psh
    psh = False
    x = random.randint(0,5)
    y = random.randint(0,5)
    xdir = 0
    ydir = 0
    while xdir == 0 or ydir == 0:
        xdir = random.randint(-1,1)
        ydir = random.randint(-1,1)
    for f in range(40):
        pos = matrix[x][y]
        pixels.set_pixel(pos,c)
        pixels.show()
        time.sleep(t)
        pos = matrix[x][y]
        pixels.set_pixel(pos,off)
        pixels.show()
        xdir = random.randint(-1,1)
        ydir = random.randint(-1,1)
        while xdir == 0 and ydir == 0:
            xdir = random.randint(-1,1)
            ydir = random.randint(-1,1)
        if x == 0 and xdir == -1:
            xdir = 1
        if x == 5 and xdir == 1:
            xdir = -1
        x = x + xdir
        
        if y == 0 and ydir == -1:
            ydir = 1
        if y == 5 and ydir == 1:
            ydir = -1
        y = y + ydir
        if psh:
            return

def button_handler(pin):
    button.irq(trigger = machine.Pin.IRQ_RISING, handler = None)
    global np, psh
    wipe(off,0.1)
    psh = True
    np = np + 1
    if np > 11:
        np = 0
    print(np)
    time.sleep(0.1)
    button.irq(trigger = machine.Pin.IRQ_RISING, handler = button_handler)

#main loop starts here

#set up interupt for button push
button.irq(trigger = machine.Pin.IRQ_RISING, handler = button_handler)

while True:
    for col in pattern:
        led_onboard.toggle()
        if np == 0:
            march(col,spd)
        elif np == 1:
            wipe(col,spd)
        elif np == 2:
            corner(col,spd)
        elif np == 3:
            rndpix(spd)
        elif np == 4:
            squares(spd)
        elif np == 5:
            spiralin(col,spd)
        elif np == 6:
            spiralout(col,spd)
        elif np == 7:
            fillout(col,spd)
        elif np == 8:
            fillin(col,spd)
        elif np == 9:
            spin(col,spd)
        elif np == 10:
            bounce(col,spd)
        elif np == 11:
            rndmove(col,spd)
