import utime, os, array, ssd1306
from machine import Pin, PWM, Timer, SoftI2C
from toneLib import allNotes, musicBoxDancer
# import rp2
i2c = machine.SoftI2C(scl=machine.Pin(5), sda=machine.Pin(4))
pin = machine.Pin(16, machine.Pin.OUT)
pin.value(0)
pin.value(1)
oled_width = 128
oled_height = 64
oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c)
oled.fill(0)
startLine = 0
leftMargin = 0
newLine = False
lineOfText = '1234567890123456'
#pageOfText = ["","","","","","",""]
pageOfText = []
def updateDisplay(displayTimer):
global newLine, pageOfText
if newLine:
linePointer = 5
oled.fill(0)
for i in range(startLine,len(pageOfText)):
oled.text(pageOfText[i], leftMargin, linePointer)
linePointer += 10
oled.show()
newLine = False
def oPrint(newText):
global pageOfText, newLine
numLines = len(pageOfText)
i=0
if numLines < 6:
pageOfText.append(newText)
else:
for i in range(0,numLines-1):
pageOfText[i] = pageOfText[i+1]
pageOfText[5]=newText
newLine = True
myDelay = 0.10
sirenToneLength = 0.012
sirenDelay = 0.003
songSpeed = 140 #bpm for 4/4
wholeNoteLength = (60/songSpeed)*4*1000 #for 4/4, in msecs.
# 1 is a whole note
# 2 is a half note
# 3 is a 3rd of bar note
# 4 is a quarter half note length
# 9 is a triplet note
# 16 is a sixtenth note length
noteTimer = Timer()
LEDTimer = Timer()
displayTimer = Timer()
playLength1 = 0
playLength2 = 0
stopNote1 = False
stopNote2 = False
playCounter1 = 100
playCounter2 = 100
getNextNote = True
noteNumber = 0 # start at the first note in array
note = musicBoxDancer[noteNumber]
mainVolume = 32000 # max of 32768 (max duty cycle)
pwm1 = machine.PWM(machine.Pin(18))
pwm2 = machine.PWM(machine.Pin(20))
myLed = Pin("LED",Pin.OUT) # Raspberry Pi Pico W: built-in LED connected to GPIO 25
songLength = len (musicBoxDancer)
print ('songLength =',songLength)
def blink(LEDTimer):
myLed.toggle()
#print('flash')
def tickNow(noteTimer):
global noteTicker
noteTicker = True
# define a melody - two dimensional list of notes and note-duration (ms)
twinkle_notes = [
(261.63, myDelay), # C4
(261.63, myDelay), # C4
(392.00, myDelay), # G4
(392.00, myDelay), # G4
(440.00, myDelay), # A4
(440.00, myDelay), # A4
(392.00, 4*myDelay), # G4
(349.23, myDelay), # F4
(349.23, myDelay), # F4
(329.63, myDelay), # E4
(329.63, myDelay), # E4
(293.66, myDelay), # D4
(293.66, myDelay), # D4
(261.63, 6*myDelay) # C4
]
def play_note(frequency, duration):
pwm1.freq(int(frequency))
pwm1.duty_u16(300)
utime.sleep(duration)
pwm1.duty_u16(0)
def play_poly_note(buzzNum, frequency, volume):
global pwm1, pwm2
frequencyHz = int (allNotes[frequency])
if buzzNum == 1:
if frequencyHz > 0:
pwm1.freq(frequencyHz)
pwm1.duty_u16(volume)
else:
pwm1.duty_u16(0) # rest
if buzzNum == 2:
if frequencyHz > 0:
pwm2.freq(frequencyHz)
pwm2.duty_u16(volume)
else:
pwm2.duty_u16(0) # rest
def stopProg():
while 1:
pwm1.deinit()
pwm2.deinit()
########################################
### Start #####
########################################
print(os.listdir('/'))
print('wholeNoteLength=', wholeNoteLength)
printNotes = 0
LEDTimer.init(freq=4, mode=Timer.PERIODIC, callback=blink)
displayTimer.init(freq=3, mode=Timer.PERIODIC, callback=updateDisplay)
noteTimer.init(freq=100, mode=Timer.PERIODIC, callback=tickNow) # updateBuzzStates serviced every 10msec (100Hz)
if 0:
for note in twinkle_notes:
play_note(note[0], note[1])
myLed.toggle()
utime.sleep(0.02)
if 0:
for i in range(20,4000,25):
print(i)
play_note(i,sirenToneLength)
utime.sleep(sirenDelay)
for i in range(4000,20,-25):
print(i)
play_note(i,sirenToneLength)
utime.sleep(sirenDelay)
noteTicker = False
barCounter = 0
decayVolume1 = 0
decayVolume2 = 0
decayRate = 1024
decayRateSlow = 128
while 1:
if getNextNote:
getNextNote = False
if (noteNumber == songLength):
print('song finished')
stopProg()
note = musicBoxDancer[noteNumber]
if note[0] == 2: # buzzer 2
play_poly_note(2, note[1], mainVolume)
decayVolume2 = mainVolume
if printNotes:
print('playing ',noteNumber, note[1], 'on buzzer 2')
playLength2 = note[2]
noteNumber += 1 # advance and also play buzzer 1
note = musicBoxDancer[noteNumber]
if note[0] == 1: # buzzer 1
play_poly_note(1, note[1], mainVolume)
decayVolume1 = mainVolume
if printNotes:
print('playing ',noteNumber, note[1], 'on buzzer 1')
playLength1 = note[2]
if note[0] == 0: # print text field
if note[1] == 'Bar':
barCounter += 1
songString = note[1]+" "+str(barCounter)
else:
songString = note[1]
oPrint(songString)
noteNumber += 1
if noteTicker == True:
noteTicker = False
if playLength1 >0:
playCounter1 = wholeNoteLength/(10*playLength1)
if printNotes:
print ('for',playCounter1, 'ticks')
playLength1 = 0
else:
if playCounter1 > 0:
playCounter1 -= 1
#volume decay WIP:
decayVolume1 = pwm1.duty_u16() # get the current duty cycle
if printNotes:
print('Vol 1 is',decayVolume1)
if decayVolume1 < decayRate:
decayVolume1 = 0
else:
decayVolume1 -= decayRate
pwm1.duty_u16(decayVolume1)
else:
stopNote1 = True
if playLength2 >0:
playCounter2 = wholeNoteLength/(10*playLength2)
if printNotes:
print ('for',playCounter2, 'ticks')
playLength2 = 0
else:
if playCounter2 > 0:
playCounter2 -= 1
decayVolume2 = pwm2.duty_u16() # get the current duty cycle
if printNotes:
print('Vol 2 is',decayVolume2)
if decayVolume2 < decayRateSlow:
decayVolume2 = 0
else:
decayVolume2 -= decayRateSlow
pwm2.duty_u16(decayVolume2)
else:
stopNote2 = True
if stopNote1 == True:
stopNote1 = False
pwm1.duty_u16(0)
getNextNote = True
if stopNote2 == True:
stopNote2 = False
pwm2.duty_u16(0)