[{"element_type":"text","content":"\n  \n  \n        \u003cp\u003eI've been working on building the updated HAL9000 using the Propmaker Feather, and tweaked the code a bit to add a couple of features. Mainly:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAnimate the LED using a slow pulse animation when HAL9000 is \"idle\" (in other words, not playing a sound)\u003c/li\u003e\n\u003cli\u003eShuffle the list of wave files, and keep track as we play our way through them; then, once we've reached the end, re-shuffle the list and start over. This prevents the same sound repeating over and over, which the current approach is prone to. It also ensures you'll hear every sound if you keep pressing the button (until the list eventually has to repeat).\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eI ordered a decal to use instead of 3D printing the \"HAL9000\" label, so I'm waiting on that before I post the photos of my build, but in the meantime, here's my updated code if anyone is interested (you'll need to add the \u003ccode\u003eadafruit_ticks.mpy\u003c/code\u003e library to your \u003ccode\u003elib\u003c/code\u003e folder in order to use this).\u003c/p\u003e\n\u003cp\u003e \u003c/p\u003e\n\u003cp\u003e \u003c/p\u003e\n      \n\n","metadata":{}},{"element_type":"code","content":"# SPDX-FileCopyrightText: 2023 Phil Burgess for Adafruit Industries (with modifications by Aaron Pendley)\n#\n# SPDX-License-Identifier: MIT\n\n\"\"\"\nHAL 9000 demo project for Adafruit Prop Maker Feather RP2040 and \"Massive\nArcade Button with LED - 100mm red.\" This simply monitors for button presses\nand then randomly plays one WAV file from the CIRCUITPY filesystem.\nNo soldering required; using quick-connects, LED and button can be wired\nto screw terminals on the Prop Maker Feather board.\nNOTE: WAV FILES MUST BE 16-BIT. This will be fixed (allowing 8-bit WAVs if\ndesired) in CircuitPython 9.0.\n\"\"\"\n\n# pylint: disable=import-error\nimport os\nimport random\nimport time\nimport audiocore\nimport audiobusio\nimport board\nimport digitalio\nimport pwmio\nimport math\nfrom adafruit_ticks import ticks_ms, ticks_diff\n\n\n# HARDWARE SETUP -----------------------------------------------------------\n\nled = pwmio.PWMOut(board.EXTERNAL_NEOPIXELS)\nled.duty_cycle = 0\nled_pulse_period = 8000\nled_timer = 0\n\n# Button is wired to GND and \"Btn\" on screw terminal header:\nbutton = digitalio.DigitalInOut(board.EXTERNAL_BUTTON)\nbutton.direction = digitalio.Direction.INPUT\nbutton.pull = digitalio.Pull.UP\n\n# Enable power to audio amp, etc.\nexternal_power = digitalio.DigitalInOut(board.EXTERNAL_POWER)\nexternal_power.direction = digitalio.Direction.OUTPUT\nexternal_power.value = True\n\n# I2S audio out\naudio = audiobusio.I2SOut(board.I2S_BIT_CLOCK, board.I2S_WORD_SELECT, board.I2S_DATA)\n\n# Find all Wave files in CIRCUITPY storage:\nwavefiles = [\n    file\n    for file in os.listdir(\"/sounds/\")\n    if (file.endswith(\".wav\") and not file.startswith(\"._\"))\n]\nprint(\"\\nAudio files found:\", wavefiles)\n\ncurrent_sound_index = 0\n\n# FUNCTIONS ----------------------------------------------------------------\n\ndef shuffle_sounds():\n    global wavefiles\n    global current_sound_index\n\n    wavefiles = sorted(wavefiles, key=lambda x: random.random())\n    current_sound_index = 0\n\n    print(\"Shuffled sounds:\", wavefiles)    \n\ndef play_next_sound():\n    global wavefiles\n    global current_sound_index\n\n    filename = wavefiles[current_sound_index]\n\n    print(\"Playing sound\", current_sound_index, \"-\", filename)    \n\n    # Go to the next random sound and reshuffle list if we're at the end\n    current_sound_index += 1\n    if current_sound_index \u003e= len(wavefiles):\n        shuffle_sounds()\n\n    \"\"\"Plays a WAV file in its entirety (function blocks until done).\"\"\"\n    with open(f\"/sounds/{filename}\", \"rb\") as file:\n        audio.play(audiocore.WaveFile(file))\n\n        # Randomly flicker the LED a bit while audio plays\n        while audio.playing:\n            led.duty_cycle = random.randint(5000, 30000)\n            time.sleep(0.1)\n\n\n# MAIN LOOP ----------------------------------------------------------------\n\nshuffle_sounds()\nlast_ticks = ticks_ms()\n\nwhile True:\n    # Update time tracking\n    now = ticks_ms()\n    dt = ticks_diff(now, last_ticks)\n    last_ticks = now\n\n    if button.value is False:\n        play_next_sound()\n\n        # Set the LED timer to fade out from 25% brightness\n        led_timer = led_pulse_period - (led_pulse_period / 4)\n\n        # Update last_ticks since play_next_sound() blocks our timing updates until it's done\n        last_ticks = ticks_ms()        \n    else:\n        # Update pulse animation\n        led_timer = (led_timer + dt) % led_pulse_period\n        sinValue = math.sin((led_timer * math.pi * 2 / led_pulse_period) + 2) + 1\n        gammaCorrected = pow(1 - (sinValue / 2), 1.8)\n        led.duty_cycle = int(gammaCorrected * 65535)","metadata":{"language":"python","linenums":false}}]