Skip to content

Add extended tone demo to examples #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 9, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions examples/macropad_tone_keypad_extended.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# SPDX-FileCopyrightText: Copyright (c) 2021 Aaron Pendley
#
# SPDX-License-Identifier: Unlicense
"""
MacroPad extended tone demo. Expands upon the basic tone demo by using
a stack to track pressed keys, allowing multiple keys to be pressed at once,
while preserving the order they were pressed. Also, improved responsiveness by
updating the Neopixels only when one of the key states has changed.
"""

from rainbowio import colorwheel
from adafruit_macropad import MacroPad

macropad = MacroPad()

# We'll show the pixels manually
macropad.pixels.auto_write = False

# Notes for each key
tones = [196, 220, 246, 262, 294, 330, 349, 392, 440, 494, 523, 587]

# When a key is pressed we'll append it to the end, and when a key is
# released we'll remove it. This results in a list of pressed keys in
# the order they were pressed.
key_pressed_stack = []

# When at least one key is pressed, this will
# be the index of the currently playing note.
playing_index = None

# Helper to convert an integer to an rgb value.
def rgb_from_int(rgb):
blue = rgb & 255
green = (rgb >> 8) & 255
red = (rgb >> 16) & 255
return red, green, blue


# Loop forever, until the heat death of the universe
# (or we lose power, whichever comes first).
while True:
# To save time, we'll only update the pixels when a key event happens.
update_pixels = False

# Process all pending events.
while macropad.keys.events:
key_event = macropad.keys.events.get()

# We need to update the pixels again at the end of the main loop.
update_pixels = True

if key_event.pressed:
# Append pressed key to the end of the stack
key_pressed_stack.append(key_event.key_number)
else:
# Remove released key from the stack
key_pressed_stack.remove(key_event.key_number)

# Turn this pixel off since the key is no longer pressed.
macropad.pixels[key_event.key_number] = 0

# How many keys are currently pressed?
pressed_count = len(key_pressed_stack)

# There are some keys pressed.
if pressed_count > 0:
# Get the most recently pressed key
top_index = key_pressed_stack[pressed_count - 1]

# If the most recently pressed key's tone isn't already playing;
if top_index != playing_index:
# If a tone was playing, stop it, so we can play the next one.
if playing_index is not None:
macropad.stop_tone()

# Play this key's tone and remember which one it is.
macropad.start_tone(tones[top_index])
playing_index = top_index

# There are no keys pressed.
else:
# If a tone was playing, stop it.
if playing_index is not None:
macropad.stop_tone()
playing_index = None

# If a key was pressed or released, update the pixels for the pressed keys.
if update_pixels:
for key_index in key_pressed_stack:
# Get the color for this key.
wheel_color = colorwheel(int(255 / 12) * key_index)

if key_index == playing_index:
# Show the currently playing key at full brightness.
macropad.pixels[key_index] = wheel_color
else:
# Dim the rest of the keys to 10% brightness.
(r, g, b) = rgb_from_int(wheel_color)
macropad.pixels[key_index] = (r * 0.1, g * 0.1, b * 0.1)

# Don't forget to show the pixels!
macropad.pixels.show()