Dictionaries allow us to associate a value with a name (generally called a key). It's more general than that, but that's probably the most common use.
A common way to construct a dictionary to use the brace notation:
>>> d = {'one': 1, 'two': 2, 'three': 3} >>> d {'one': 1, 'three': 3, 'two': 2}
Notice that dictionaries are not ordered. That's fine, because they don't use numeric indices, they use keys.
As with lists, we can find out how many key-value pairs are in a dictionary using:
>>> len(d) 3
Accessing data in a dictionary is done similarly to lists:
>>> d['three'] 3
as is changing it:
>>> d['three'] = 'not3' >>> d {'one': 1, 'three': 'not3', 'two': 2}
Adding a key/value pair to a dictionary is the same as modifying one:
>>> d['four'] = 4 >>> d {'four': 4, 'one': 1, 'two': 2, 'three': 'not3'}
To remove from a dictionary we use the del
function:
>>> del(d['three']) >>> d {'four': 4, 'one': 1, 'two': 2}
Finally, we can check if a dictionary contains a specific key:
>>> 'one' in d True >>> 'three' not in d True >>> 'three' in d False
Formats - Songbook
So we have notes represented by tuples that we can put together in a list to make a song. What if we want multiple songs? We could have each in a separate variable. Let's add the additional requirement that we want to connect an I2C OLED display to show a list of songs that we can select from. Having songs in separate variables means that everything has to be hardcoded. That's seldom a good idea. What we'd like is to have things stored in such a way that we just have to add a song and have the menu automatically be updated to reflect it. We can do this by storing them in a dictionary, keyed by name (edited for brevity):
songbook = {'Twinkle Twinkle': [(C4, 0.5), (C4, 0.5), (G4, 0.5), (G4, 0.5), (A4, 0.5), ...], 'ItsyBitsy Spider': [(G4, 0.5), (C4, 0.5), (C4, 0.5), (C4, 0.5), (D4, 0.5), ...], 'Old MacDonald': [(G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (E4, 0.5), ...] }
With that done, we can get the names of the songs by songbook.keys()
. This isn't a list, although it can be used for some list-like things. It can't be indexed, however. We need to convert it to a list in order to be able to do that: list(songbook.keys())
. While we're at it, we should go ahead and sort it so that it will display in alphabetical order: sorted(list(songbook.keys()))
.
Here is the complete code:
# SPDX-FileCopyrightText: 2018 Dave Astels for Adafruit Industries # # SPDX-License-Identifier: MIT import time import board from adafruit_debouncer import Debouncer import busio as io import digitalio import pwmio import adafruit_ssd1306 i2c = io.I2C(board.SCL, board.SDA) reset_pin = digitalio.DigitalInOut(board.D11) oled = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin) select = digitalio.DigitalInOut(board.D7) select.direction = digitalio.Direction.INPUT select.pull = digitalio.Pull.UP button_select = Debouncer(select) play = digitalio.DigitalInOut(board.D9) play.direction = digitalio.Direction.INPUT play.pull = digitalio.Pull.UP button_play = Debouncer(play) C4 = 261 C_SH_4 = 277 D4 = 293 D_SH_4 = 311 E4 = 329 F4 = 349 F_SH_4 = 369 G4 = 392 G_SH_4 = 415 A4 = 440 A_SH_4 = 466 B4 = 493 # pylint: disable=line-too-long songbook = {'Twinkle Twinkle': [(C4, 0.5), (C4, 0.5), (G4, 0.5), (G4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 1.0), (0, 0.5), (F4, 0.5), (F4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (D4, 0.5), (C4, 0.5), (0, 0.5), (G4, 0.5), (G4, 0.5), (F4, 0.5), (F4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5), (G4, 0.5), (G4, 0.5), (F4, 0.5), (F4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5), (C4, 0.5), (C4, 0.5), (G4, 0.5), (G4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 1.0), (0, 0.5), (F4, 0.5), (F4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (D4, 0.5), (C4, 0.5), (0, 0.5)], 'ItsyBitsy Spider': [(G4, 0.5), (C4, 0.5), (C4, 0.5), (C4, 0.5), (D4, 0.5), (E4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (C4, 0.5), (D4, 0.5), (E4, 0.5), (C4, 0.5), (0, 0.5), (E4, 0.5), (E4, 0.5), (F4, 0.5), (G4, 0.5), (G4, 0.5), (F4, 0.5), (E4, 0.5), (F4, 0.5), (G4, 0.5), (E4, 0.5), (0, 0.5)], 'Old MacDonald': [(G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5), (B4, 0.5), (B4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 0.5), (0, 0.5), (D4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5), (B4, 0.5), (B4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 0.5), (0, 0.5), (D4, 0.5), (D4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (D4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (0, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (0, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (0, 0.5), (G4, 0.5), (G4, 0.5), (G4, 0.5), (D4, 0.5), (E4, 0.5), (E4, 0.5), (D4, 0.5), (0, 0.5), (B4, 0.5), (B4, 0.5), (A4, 0.5), (A4, 0.5), (G4, 0.5), (0, 0.5)] } # pylint: enable=line-too-long def play_note(note): if note[0] != 0: pwm = pwmio.PWMOut(board.D12, duty_cycle = 0, frequency=note[0]) # Hex 7FFF (binary 0111111111111111) is half of the largest value for a 16-bit int, # i.e. 50% pwm.duty_cycle = 0x7FFF time.sleep(note[1]) if note[0] != 0: pwm.deinit() def play_song(songname): for note in songbook[songname]: play_note(note) def update(songnames, selected): oled.fill(0) line = 0 for songname in songnames: if line == selected: oled.text(">", 0, line * 8) oled.text(songname, 10, line * 8) line += 1 oled.show() selected_song = 0 song_names = sorted(list(songbook.keys())) while True: button_select.update() button_play.update() update(song_names, selected_song) if button_select.fell: print("select") selected_song = (selected_song + 1) % len(songbook) elif button_play.fell: print("play") play_song(song_names[selected_song])
Text editor powered by tinymce.