diff --git a/Dial-a-Song/code.py b/Dial-a-Song/code.py new file mode 100644 index 000000000..fa02b70bd --- /dev/null +++ b/Dial-a-Song/code.py @@ -0,0 +1,141 @@ +# SPDX-FileCopyrightText: 2022 John Park for Adafruit Industries +# +# SPDX-License-Identifier: MIT +# +# DTMF keypad phone Dial-a-Song +import time +import random +import board +import keypad +from audiocore import WaveFile +from audiopwmio import PWMAudioOut as AudioOut # for RP2040 etc +import audiomixer + +# time.sleep(3) # let USB settle during development, remove when on battery + +km = keypad.KeyMatrix( + # 2500 phone ignoring first column store/redial/memory. reverse mount on Feather RP2040 + column_pins=( board.A3, board.A2, board.A1,), + row_pins=( + board.D24, + board.D25, + board.SCK, + board.MOSI, + ), +) + +numbers = { + "8675309" : "songs/beepbox.wav", + "6358393" : "songs/streetchicken.wav", + "5551212" : "songs/carpeter.wav", + "7654321" : "songs/daisy.wav" +} + +ringing = "songs/full_ring.wav" +wrong_number = "songs/blank_number.wav" +dial_tone = "songs/dial_tone_loop.wav" +busy_signal = "songs/busy_loop.wav" + +button_tones = [ + "dtmf/tt_1.wav", "dtmf/tt_2.wav", "dtmf/tt_3.wav", + "dtmf/tt_4.wav", "dtmf/tt_5.wav", "dtmf/tt_6.wav", + "dtmf/tt_7.wav", "dtmf/tt_8.wav", "dtmf/tt_9.wav", + "dtmf/tt_star.wav", "dtmf/tt_0.wav", "dtmf/tt_pound.wav" +] + +digits_entered = 0 # counter +dialed = [] # list of digits user enters to make one 7 digit number +dialed_str = "" # stores the phone number string for dictionary comparison + +audio = AudioOut(board.TX) # PWM out pin +mixer = audiomixer.Mixer( + voice_count=4, + sample_rate=22050, + channel_count=1, + bits_per_sample=16, + samples_signed=True, +) +audio.play(mixer) +mixer.voice[0].level = 1.0 # dial tone voice +mixer.voice[1].level = 1.0 # touch tone voice +mixer.voice[2].level = 0.0 # song/message voice +mixer.voice[3].level = 0.0 # busy signal + +wave_file0 = open(dial_tone, "rb") +wave0 = WaveFile(wave_file0) +mixer.voice[0].play(wave0, loop=True) # play dial tone + +wave_file2 = open(wrong_number, "rb") +wave2 = WaveFile(wave_file2) + +wave_file3 = open(busy_signal, "rb") +wave3 = WaveFile(wave_file3) +mixer.voice[3].play(wave3, loop=True) # play dial tone + + +def reset_number(): + # pylint: disable=global-statement + global digits_entered, dialed, dialed_str + digits_entered = 0 + dialed = [] + dialed_str = "" + km.events.clear() + + +while True: + + event = km.events.get() # check for keypad presses + if event: + if event.pressed: + mixer.voice[0].level = 0.0 # mute the dial tone + wave_file1 = open(button_tones[event.key_number], "rb") # play Touch Tone + wave1 = WaveFile(wave_file1) + mixer.voice[1].play(wave1) + if event.key_number == 9 or event.key_number == 11: # check for special keys + if event.key_number == 9: # pressed the '*' key + reset_number() # or make some cool new function for this key + if event.key_number == 11: # pressed the '#' key + reset_number() # or make some cool new function for this key + + else: # number keys + if digits_entered < 7: # adding up to full number + # convert event to number printed on the keypad button, append to string + if event.key_number < 9: # 1-9 on keypad + dialed.append(event.key_number+1) + if event.key_number == 10: # the 0 key, ignore '*' and "#' + dialed.append(0) + dialed_str = "".join(str(n) for n in dialed) + digits_entered = digits_entered + 1 # increment counter + + if digits_entered == 7: # a full number has been entered + if not mixer.voice[2].playing: + dialed_str = "".join(str(n) for n in dialed) + if dialed_str in numbers: # check if dialed string is one in the directory + value = numbers[dialed_str] + time.sleep(0.6) + + wave_file2 = open(ringing, "rb") # ring before it answers + wave2 = WaveFile(wave_file2) + mixer.voice[2].level = 1.0 + mixer.voice[2].play(wave2, loop=True) + + time.sleep(random.uniform(4.0, 9.5)) # random ring before "answer" + + wave_file2 = open(value, "rb") # answered + wave2 = WaveFile(wave_file2) + mixer.voice[2].level = 1.0 + mixer.voice[2].play(wave2, loop=True) + + else: # number is not in directory + time.sleep(0.5) + weighted_coin_toss = random.randint(0, 4) + if weighted_coin_toss < 3: # favor the "not in service" message + mixer.voice[2].level = 1.0 + mixer.voice[2].play(wave2) + else: + mixer.voice[3].level = 1.0 + + reset_number() + + if mixer.voice[2].playing: + reset_number() # stop #s dialed during message play from doing anything diff --git a/Dial-a-Song/dtmf/tt_0.wav b/Dial-a-Song/dtmf/tt_0.wav new file mode 100755 index 000000000..19d88181e Binary files /dev/null and b/Dial-a-Song/dtmf/tt_0.wav differ diff --git a/Dial-a-Song/dtmf/tt_1.wav b/Dial-a-Song/dtmf/tt_1.wav new file mode 100755 index 000000000..b71ab81fd Binary files /dev/null and b/Dial-a-Song/dtmf/tt_1.wav differ diff --git a/Dial-a-Song/dtmf/tt_2.wav b/Dial-a-Song/dtmf/tt_2.wav new file mode 100755 index 000000000..ea164dc1a Binary files /dev/null and b/Dial-a-Song/dtmf/tt_2.wav differ diff --git a/Dial-a-Song/dtmf/tt_3.wav b/Dial-a-Song/dtmf/tt_3.wav new file mode 100755 index 000000000..52700fdb5 Binary files /dev/null and b/Dial-a-Song/dtmf/tt_3.wav differ diff --git a/Dial-a-Song/dtmf/tt_4.wav b/Dial-a-Song/dtmf/tt_4.wav new file mode 100755 index 000000000..8da36ae28 Binary files /dev/null and b/Dial-a-Song/dtmf/tt_4.wav differ diff --git a/Dial-a-Song/dtmf/tt_5.wav b/Dial-a-Song/dtmf/tt_5.wav new file mode 100755 index 000000000..21dbc79ad Binary files /dev/null and b/Dial-a-Song/dtmf/tt_5.wav differ diff --git a/Dial-a-Song/dtmf/tt_6.wav b/Dial-a-Song/dtmf/tt_6.wav new file mode 100755 index 000000000..0b64bc82f Binary files /dev/null and b/Dial-a-Song/dtmf/tt_6.wav differ diff --git a/Dial-a-Song/dtmf/tt_7.wav b/Dial-a-Song/dtmf/tt_7.wav new file mode 100755 index 000000000..40cc12dcb Binary files /dev/null and b/Dial-a-Song/dtmf/tt_7.wav differ diff --git a/Dial-a-Song/dtmf/tt_8.wav b/Dial-a-Song/dtmf/tt_8.wav new file mode 100755 index 000000000..f6319ef32 Binary files /dev/null and b/Dial-a-Song/dtmf/tt_8.wav differ diff --git a/Dial-a-Song/dtmf/tt_9.wav b/Dial-a-Song/dtmf/tt_9.wav new file mode 100755 index 000000000..085243ce6 Binary files /dev/null and b/Dial-a-Song/dtmf/tt_9.wav differ diff --git a/Dial-a-Song/dtmf/tt_pound.wav b/Dial-a-Song/dtmf/tt_pound.wav new file mode 100755 index 000000000..b07f1adb5 Binary files /dev/null and b/Dial-a-Song/dtmf/tt_pound.wav differ diff --git a/Dial-a-Song/dtmf/tt_star.wav b/Dial-a-Song/dtmf/tt_star.wav new file mode 100755 index 000000000..b518cf224 Binary files /dev/null and b/Dial-a-Song/dtmf/tt_star.wav differ diff --git a/Dial-a-Song/songs/beepbox.wav b/Dial-a-Song/songs/beepbox.wav new file mode 100644 index 000000000..61a64bf60 Binary files /dev/null and b/Dial-a-Song/songs/beepbox.wav differ diff --git a/Dial-a-Song/songs/blank_number.wav b/Dial-a-Song/songs/blank_number.wav new file mode 100755 index 000000000..b9c1127cc Binary files /dev/null and b/Dial-a-Song/songs/blank_number.wav differ diff --git a/Dial-a-Song/songs/busy_loop.wav b/Dial-a-Song/songs/busy_loop.wav new file mode 100644 index 000000000..9252c5564 Binary files /dev/null and b/Dial-a-Song/songs/busy_loop.wav differ diff --git a/Dial-a-Song/songs/carpeter.wav b/Dial-a-Song/songs/carpeter.wav new file mode 100644 index 000000000..68d926eef Binary files /dev/null and b/Dial-a-Song/songs/carpeter.wav differ diff --git a/Dial-a-Song/songs/daisy.wav b/Dial-a-Song/songs/daisy.wav new file mode 100644 index 000000000..195c7f437 Binary files /dev/null and b/Dial-a-Song/songs/daisy.wav differ diff --git a/Dial-a-Song/songs/dial_tone_loop.wav b/Dial-a-Song/songs/dial_tone_loop.wav new file mode 100644 index 000000000..54830ac3b Binary files /dev/null and b/Dial-a-Song/songs/dial_tone_loop.wav differ diff --git a/Dial-a-Song/songs/full_ring.wav b/Dial-a-Song/songs/full_ring.wav new file mode 100644 index 000000000..40e4998a7 Binary files /dev/null and b/Dial-a-Song/songs/full_ring.wav differ diff --git a/Dial-a-Song/songs/streetchicken.wav b/Dial-a-Song/songs/streetchicken.wav new file mode 100644 index 000000000..5cb8502eb Binary files /dev/null and b/Dial-a-Song/songs/streetchicken.wav differ