# SPDX-License-Identifier: MIT # # Little christmas candle # # Author: Nils Freydank # Year: 2022 # Copyright: MIT import json import machine import time pin_piezo = machine.Pin(12) def _note_to_freq(note_name: str) -> int: """ Translate note names from strings into frequency values. """ freq: int = 0 # frequencies, see e.g. # https://en.wikipedia.org/wiki/Piano_key_frequencies note_names: dict = { "c4": 262, "cis4": 277, "d4": 294, "e4": 330, "f4": 349, "fis4": 370, "g4": 392, "a4": 440, "b4": 466, "h4": 494, "c5": 523, "cis5": 554, "d5": 587, "e5": 659, "f5": 698, "fis5": 740, "g5": 784, "a5": 880, "b5": 923, "h5": 988, "c6": 1047, } try: freq = note_names[note_name] except KeyError: freq = -1 print(f"exc in _note_to_freq() for {note_name}.") return freq def _len_to_second(len_name: str, len_scaling: float = 0.6) -> float: time: float = 0.0 len_names = { "_t": 0.125 * len_scaling, # thirty-second note or pause "_s": 0.25 * len_scaling, # sixteenth note or pause "_e": 0.5 * len_scaling, # eight note or pause "_q": 1.0 * len_scaling, # quarter note or pause "_h": 2.0 * len_scaling, # half note or pause "_f": 4.0 * len_scaling, # whole note or pause } try: for elem in len_name.split("+"): time += len_names[elem.replace(" ", "")] except KeyError: time = 0.0 print(f"exc in _len_to_second() for {elem}.") print("Do you have a typo there, e.g. 'a' + 'b' instead of 'a + b'?") return time def play_note(note_name: str, duration: str, loud: bool = False) -> int: if loud: duty_cycle: int = 16_000 else: duty_cycle: int = 400 real_pwm_freq: int = 0 pwm_piezo = machine.PWM(pin_piezo) pwm_piezo.freq(_note_to_freq(note_name)) real_pwm_freq = pwm_piezo.freq() pwm_piezo.duty_u16(duty_cycle) time.sleep(_len_to_second(duration)) pwm_piezo.duty_u16(0) time.sleep(0.05) return real_pwm_freq def pause(duration: str) -> None: time.sleep(_len_to_second(duration)) time.sleep(0.05) def play_music(file_name: str = "o-tannenbaum.json") -> None: data: dict = {} try: with open(file_name, "r") as f: data = json.load(f) try: if data["metadata"]["format"] == "json-0.1.0": for notes in data["music"]: for note in notes.keys(): if note == "0": pause(notes[note]) else: play_note(note, notes[note]) elif data["metadata"]["format"] == "json-0.2.0": pass except: print(f"play_oh_tannnebaum() failed to parse {data}.") except FileNotFoundError: print("Could not load the JSON file containing the song's details.") # vim:fileencoding=utf-8:ts=4:syntax=python:expandtab