107 lines
2.7 KiB
Python
107 lines
2.7 KiB
Python
from microbit import *
|
|
import music
|
|
|
|
# Constants
|
|
note_names: list[str] = [
|
|
"C",
|
|
"Db",
|
|
"D",
|
|
"Eb",
|
|
"E",
|
|
"F",
|
|
"Gb",
|
|
"G",
|
|
"Ab",
|
|
"A",
|
|
"Bb",
|
|
"B",
|
|
]
|
|
max_octave: int = 8
|
|
max_midi_note: int = 127
|
|
|
|
images_set = {
|
|
"A": Image("09900:" "90090:" "99990:" "90090:" "90090"),
|
|
"B": Image("99900:" "90090:" "99900:" "90090:" "99900"),
|
|
"C": Image("09990:" "90000:" "90000:" "90000:" "09990"),
|
|
"D": Image("99900:" "90090:" "90090:" "90090:" "99900"),
|
|
"E": Image("99990:" "90000:" "99900:" "90000:" "99990"),
|
|
"F": Image("99990:" "90000:" "99900:" "90000:" "90000"),
|
|
"G": Image("09990:" "90000:" "90990:" "90090:" "09990"),
|
|
}
|
|
|
|
# Logic control
|
|
loop: bool = True
|
|
tone: bool = False
|
|
midi_key: int = 69
|
|
|
|
|
|
# Fetch the base image for the note letter from the global dictionary,
|
|
# Then embellish it with the octave pattern (in binary) and potential flat flag
|
|
def get_image(note_letter: str, octave: int) -> Image:
|
|
base_letter = note_letter[0]
|
|
base_img = images_set[base_letter]
|
|
if len(note_letter) > 1 and note_letter[1] == "b":
|
|
base_img.set_pixel(4, 4, 2)
|
|
else:
|
|
base_img.set_pixel(4, 4, 0)
|
|
binary_big_e: str = bin(octave)[2:]
|
|
binary_little_e = "".join(
|
|
reversed(list(binary_big_e))
|
|
) # one cannot simply [::-1] in micropy
|
|
bit_length = len(binary_little_e)
|
|
for i in range(4):
|
|
if i < bit_length and binary_little_e[i] == "1":
|
|
base_img.set_pixel(4, i, 6)
|
|
else:
|
|
base_img.set_pixel(4, i, 0)
|
|
return base_img
|
|
|
|
|
|
def get_note(key: int) -> tuple:
|
|
return ((note_names[key % 12]), ((key // 12) - 1))
|
|
|
|
|
|
def manage_tone(midi_key):
|
|
global tone
|
|
if pin_logo.is_touched() and tone == False:
|
|
note = get_note(midi_key)
|
|
print(str(note[0]), str(note[1]))
|
|
music.play(str(note[0]) + str(note[1]) + ":4", wait=False, loop=True)
|
|
tone = True
|
|
elif pin_logo.is_touched() == False and tone == True:
|
|
music.stop()
|
|
tone = False
|
|
|
|
|
|
def manage_display(midi_key):
|
|
note = get_note(midi_key)
|
|
note_letter = note[0]
|
|
octave = note[1]
|
|
display.show(get_image(note_letter, octave), wait=False, loop=True)
|
|
|
|
|
|
def log():
|
|
note = get_note(midi_key)
|
|
print(midi_key, "-", note[0], "[", note[1], "]")
|
|
|
|
|
|
manage_display(midi_key)
|
|
while loop:
|
|
input = (button_a.was_pressed(), button_b.was_pressed())
|
|
update = False
|
|
if input == (False, False):
|
|
pass
|
|
elif input == (True, False):
|
|
update = True
|
|
midi_key = (midi_key - 1) % max_midi_note
|
|
elif input == (False, True):
|
|
update = True
|
|
midi_key = (midi_key + 1) % max_midi_note
|
|
else:
|
|
pass
|
|
if update:
|
|
log()
|
|
manage_display(midi_key)
|
|
manage_tone(midi_key)
|
|
sleep(100)
|