|
| 1 | +# SPDX-FileCopyrightText: 2023 Phil Burgess for Adafruit Industries |
| 2 | +# |
| 3 | +# SPDX-License-Identifier: MIT |
| 4 | + |
| 5 | +""" |
| 6 | +HAL 9000 demo project for Adafruit Prop Maker Feather RP2040 and "Massive |
| 7 | +Arade Button with LED - 100mm red." This simply monitors for button presses |
| 8 | +and then randomly plays one WAV file from the CIRCUITPY filesystem. |
| 9 | +No soldering required; using quick-connects, LED and button can be wired |
| 10 | +to screw terminals on the Prop Maker Feather board. |
| 11 | +NOTE: WAV FILES MUST BE 16-BIT. This will be fixed (allowing 8-bit WAVs if |
| 12 | +desired) in CircuitPython 9.0. |
| 13 | +""" |
| 14 | + |
| 15 | +# pylint: disable=import-error |
| 16 | +import os |
| 17 | +import random |
| 18 | +import time |
| 19 | +import audiocore |
| 20 | +import audiobusio |
| 21 | +import board |
| 22 | +import digitalio |
| 23 | +import pwmio |
| 24 | + |
| 25 | + |
| 26 | +# HARDWARE SETUP ----------------------------------------------------------- |
| 27 | + |
| 28 | +# LED+ is wired to "Neo" pin on screw terminal header, LED- to GND. |
| 29 | +# The LED inside the button is NOT a NeoPixel, just a normal passive LED, |
| 30 | +# but that's okay here -- the "Neo" pin can also function like a simple |
| 31 | +# 5V digital output or PWM pin. |
| 32 | +led = pwmio.PWMOut(board.EXTERNAL_NEOPIXELS) |
| 33 | +led.duty_cycle = 65535 # LED ON by default |
| 34 | + |
| 35 | +# Button is wired to GND and "Btn" on screw terminal header: |
| 36 | +button = digitalio.DigitalInOut(board.EXTERNAL_BUTTON) |
| 37 | +button.direction = digitalio.Direction.INPUT |
| 38 | +button.pull = digitalio.Pull.UP |
| 39 | + |
| 40 | +# Enable power to audio amp, etc. |
| 41 | +external_power = digitalio.DigitalInOut(board.EXTERNAL_POWER) |
| 42 | +external_power.direction = digitalio.Direction.OUTPUT |
| 43 | +external_power.value = True |
| 44 | + |
| 45 | +# I2S audio out |
| 46 | +audio = audiobusio.I2SOut(board.I2S_BIT_CLOCK, board.I2S_WORD_SELECT, board.I2S_DATA) |
| 47 | + |
| 48 | +# Find all Wave files in CIRCUITPY storage: |
| 49 | +wavefiles = [ |
| 50 | + file |
| 51 | + for file in os.listdir("/sounds/") |
| 52 | + if (file.endswith(".wav") and not file.startswith("._")) |
| 53 | +] |
| 54 | +print("Audio files found:", wavefiles) |
| 55 | + |
| 56 | +# FUNCTIONS ---------------------------------------------------------------- |
| 57 | + |
| 58 | + |
| 59 | +def play_file(filename): |
| 60 | + """Plays a WAV file in its entirety (function blocks until done).""" |
| 61 | + print("Playing", filename) |
| 62 | + with open(f"/sounds/{filename}", "rb") as file: |
| 63 | + audio.play(audiocore.WaveFile(file)) |
| 64 | + # Randomly flicker the LED a bit while audio plays |
| 65 | + while audio.playing: |
| 66 | + led.duty_cycle = random.randint(5000, 30000) |
| 67 | + time.sleep(0.1) |
| 68 | + led.duty_cycle = 65535 # Back to full brightness |
| 69 | + |
| 70 | + |
| 71 | +# MAIN LOOP ---------------------------------------------------------------- |
| 72 | + |
| 73 | + |
| 74 | +# Loop simply watches for a button press (button pin pulled to GND, thus |
| 75 | +# False) and then plays a random WAV file. Because the WAV-playing function |
| 76 | +# will take a few seconds, this doesn't even require button debouncing. |
| 77 | +while True: |
| 78 | + if button.value is False: |
| 79 | + play_file(random.choice(wavefiles)) |
0 commit comments