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)