##
## Mega Simon Says in Micropython ##
## by Hari Wiguna, 2024 ###
##
from machine import Pin, PWM
import time
import random
ios = [23,22,21,19,18,5,17,16,4,0,2,15,8,7,6,11,10,9,13,12,14,27,26,25] # These are GPIO pins. Each connected to an LED AND a push button
freqs = [261,293,329,349,369,392,415,440,466,493,523,554,587,622,659,698,739,783,830,880,932,987,1046,1108,1174,1244,1318] # must have at least same # of elements as ios
sequence = []
def InitPinsAsInputs():
for p in ios:
Pin(p, Pin.IN, Pin.PULL_UP)
def TestLeds():
for i,p in enumerate(ios):
led = Pin(p, Pin.OUT)
led.value(0) # bring LED cathode to ground to turn LED on.
buzz(i,.4)
Pin(p, Pin.IN, Pin.PULL_UP) # turn io into input to turn off the led
def buzz(freqIndex, durationSecs):
buzzer = PWM(Pin(32))
buzzer.freq(freqs[freqIndex])
timeToStop = time.ticks_ms() + durationSecs*1000
buzzer.duty(512)
time.sleep(durationSecs)
buzzer.duty(0)
def GameOver(score):
for i in reversed(range(len(freqs))):
buzz(i,.08)
print("Game over! Your Score:", score)
def readButtons(waitfor):
pressed = -1
# Prepare to read buttons
buttons = []
for p in ios:
buttons.append( Pin(p, Pin.IN, Pin.PULL_UP) )
timeout = time.ticks_ms() + waitfor
while time.ticks_ms() < timeout and pressed == -1:
for i,b in enumerate(buttons):
if b.value() == 0:
pressed = i
buzz(i, 0.5)
break
time.sleep(0.1)
return pressed
#== Setup ==
InitPinsAsInputs()
#TestLeds()
print("Ready?")
time.sleep(1)
# *** MAIN ***
isGameOver = False
score = 0
print(isGameOver)
while not isGameOver:
#== Add random to sequence ==
dice_roll = random.randint(0, len(ios)-1)
sequence.append(dice_roll)
#== Play sequence ==
print("Simon Says: ")
for s in sequence:
p = ios[s]
print(s, end=", ")
led = Pin(p, Pin.OUT)
led.value(0) # bring LED cathode to ground to turn LED on.
buzz(s, 0.5)
Pin(p, Pin.IN, Pin.PULL_UP) # turn io into input to turn off the led
time.sleep(.5)
print()
#== Take in user's input ==
print("You say: ")
seqIndex = 0
while not isGameOver and seqIndex<len(sequence):
#== Wait for user input for 2 seconds==
pressed = readButtons(2000)
print(pressed, end=", ")
#== if timeout -> game over ==
if pressed == -1:
isGameOver = True
else:
#== if received button press, compare it to sequence, if wrong -> game over ==
if pressed == sequence[seqIndex]:
seqIndex = seqIndex + 1
score = seqIndex
else:
isGameOver = True
# loop back to check next in sequence.
# if no more, then make the sequence longer
print()
if isGameOver:
GameOver(score)
else:
time.sleep(2) # Pause before starting new round