from machine import Pin, PWM, Timer
from neopixel import NeoPixel
from time import sleep
from random import randint
INTER_TONES_GAP = 80
class Stimme:
noteNo = {'q':39, 'c':40, 'd':42, 'e':44, 'f':45, 'g':47, 'a':49, 'h':51,
'b':51, 'C':52, 'D':54, 'E':56, 'F':57, 'G':59, 'A':61, 'H':63,
'B':51, 'p':-22, 'Q':55, 'j':48}
def __init__(self, pin, defaultLen, lenx, bass):
self.defaultLen = defaultLen
self.lenx = lenx
self.__stringPos = 0
self.oktave = 4
self.bass = bass
self.playing = True
self.endless = False
self.lp = PWM(Pin(pin))
self.lp.duty_u16(8000)
#self.pin = pin #wegnehmen
def tonOff(self, event):
#self.lp.freq(20000)
self.lp.deinit()
def setStimme(self, notenstring):
while ' ' in notenstring:
i = notenstring.index(' ')
notenstring = notenstring[:i] + notenstring[i+1:]
self.notenstring = notenstring
def frequency(self, n):
n += 12*(self.oktave-4)
if self.bass:
n -= 21
return round(440*2**((n-49)/12))
def setEndless(self):
self.endless = True
def halt(self):
self.playing = False
def replay(self):
self.playing = True
def play(self, event=0):
while self.notenstring[self.__stringPos] == 'v':
self.__stringPos += 1
self.oktave -= 1
while self.notenstring[self.__stringPos] == '^':
self.__stringPos += 1
self.oktave += 1
self.note = self.notenstring[self.__stringPos]
self.__stringPos += 1
if len(self.notenstring) > self.__stringPos:
self.dur = self.notenstring[self.__stringPos]
else:
self.dur = 'x'
if self.dur in '1248':
self.dur = int(self.dur)
self.__stringPos += 1
else:
self.dur = self.defaultLen
self.playLen = round(self.lenx / self.dur)
if self.note in Stimme.noteNo:
f = self.frequency(Stimme.noteNo[self.note])
if f<8:
self.lp.deinit()
else:
self.lp.freq(f)
#print(' '*15*self.pin, f'{f} Hz, {self.playLen} ms')
Timer(period=self.playLen-INTER_TONES_GAP, mode=Timer.ONE_SHOT, callback=self.tonOff)
if len(self.notenstring) > self.__stringPos and self.playing:
Timer(period=self.playLen, mode=Timer.ONE_SHOT, callback=self.play)
else:
if self.endless:
self.__stringPos = 0
Timer(period=2000, mode=Timer.ONE_SHOT, callback=self.play)
class Sound:
stimmen = []
def __init__(self, tonart, speedPerTakt, defaultLen=4, taktZähler=4, taktNenner=4):
self.tonart = tonart
self.speedPerTakt = speedPerTakt
self.defaultLen = defaultLen
self.taktZähler = taktZähler
self.taktNenner = taktNenner
self.lenx = speedPerTakt / taktNenner
def addStimme(self, pin, notenstring, bass=False):
stimme = Stimme(pin, self.defaultLen, self.lenx, bass)
stimme.setStimme(notenstring)
Sound.stimmen += [stimme]
@classmethod
def replay(cls):
for stimme in cls.stimmen:
stimme.replay()
stimme.play()
@classmethod
def halt(cls):
for stimme in cls.stimmen:
stimme.halt()
@classmethod
def setEndless(cls):
for stimme in cls.stimmen:
stimme.setEndless()
@classmethod
def play(cls):
for stimme in cls.stimmen:
stimme.play()
def pressUp(event):
global dir
dir = 'n'
def pressDown(event):
global dir
dir = 's'
def pressLeft(event):
global dir
dir = 'w'
def pressRight(event):
global dir
dir = 'e'
def c(x, y):
return 8*y + x
def newApple():
global apX, apY
while posInSnake(apX, apY):
apX = randint(0, 7)
apY = randint(0, 7)
np[c(apX,apY)] = (200, 0, 0)
def posInSnake(x, y, begin=0):
global snakelst
end = len(snakelst)-begin
isit = False
for glied in snakelst[:end]:
if glied[0]==x and glied[1]==y:
isit = True
return isit
def snakeMove(dir):
global kopfX, kopfY, snakelst, lenght, apX, apY
if dir == 'n':
kopfY -= 1
elif dir == 's':
kopfY += 1
elif dir == 'e':
kopfX += 1
elif dir == 'w':
kopfX -= 1
np[c(kopfX,kopfY)] = (0, 0, 255)
if dir != '':
snakelst += [ (kopfX, kopfY) ]
if len(snakelst) > lenght:
end = snakelst.pop(0)
clsPix(end[0], end[1])
if kopfX==apX and kopfY==apY:
lenght += 1
newApple()
if not(0<=kopfX<=7 and 0<=kopfY<=7) or posInSnake(kopfX, kopfY, 1):
for i in range(0, 64):
np[i] = (0, 0, 0)
for i in range(0, 8):
np[c(i, i)] = (200, 0, 0)
np[c(i, 7-i)] = (200, 0, 0)
np.write()
sleep(1)
newGame()
def clsPix(x, y):
if (x+y)%2==0:
np[c(x,y)] = (50, 100, 50)
else:
np[c(x,y)] = (50, 100, 00)
def newGame():
global kopfX, kopfY, apX, apY, snakelst, lenght, dir
for x in range(0, 8):
for y in range(0, 8):
clsPix(x, y)
kopfX = randint(-1, 6)
kopfY = randint(0, 7)
snakelst = [ (kopfX, kopfY) ]
lenght = 1
dir = ''
apX = randint(0, 7)
apY = randint(0, 7)
snakeMove('e')
newApple()
np.write()
######### main ##################
Up = Pin(18, Pin.IN, Pin.PULL_DOWN)
Up.irq(trigger=Pin.IRQ_RISING, handler=pressUp)
Down = Pin(17, Pin.IN, Pin.PULL_DOWN)
Down.irq(trigger=Pin.IRQ_RISING, handler=pressDown)
Left = Pin(16, Pin.IN, Pin.PULL_DOWN)
Left.irq(trigger=Pin.IRQ_RISING, handler=pressLeft)
Right = Pin(19, Pin.IN, Pin.PULL_DOWN)
Right.irq(trigger=Pin.IRQ_RISING, handler=pressRight)
pin = Pin(0, Pin.OUT)
np = NeoPixel(pin, 64)
lied = Sound('C-Dur', 4000)
lied.addStimme(2, 'cdef g2g2 aaaa g1 aaaa g1 ffff e2e2 gggg c1 pppp')
lied.addStimme(4, 'cqcd e2e2 ffff e1 ffff e1 dddd c2c2 q1 c1 pppp')
lied.play()
lied.setEndless()
newGame()
while True:
snakeMove(dir)
np.write()
sleep(.5)