Skip to content

Commit 324fa46

Browse files
committed
Add extended tone demo to examples
1 parent 7c1a136 commit 324fa46

File tree

1 file changed

+102
-0
lines changed

1 file changed

+102
-0
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2021 Aaron Pendley
2+
#
3+
# SPDX-License-Identifier: Unlicense
4+
"""
5+
MacroPad extended tone demo. Expands upon the basic tone demo by using
6+
a stack to track pressed keys, allowing multiple keys to be pressed at once,
7+
while preserving the order they were pressed. Also, improved responsiveness by
8+
updating the Neopixels only when one of the key states has changed.
9+
"""
10+
11+
from adafruit_macropad import MacroPad
12+
from rainbowio import colorwheel
13+
14+
macropad = MacroPad()
15+
16+
# We'll show the pixels manually
17+
macropad.pixels.auto_write = False
18+
19+
# Notes for each key
20+
tones = [196, 220, 246, 262, 294, 330, 349, 392, 440, 494, 523, 587]
21+
22+
# When a key is pressed we'll append it to the end, and when a key is
23+
# released we'll remove it. This results in a list of pressed keys in
24+
# the order they were pressed.
25+
key_pressed_stack = []
26+
27+
# When at least one key is pressed, this will
28+
# be the index of the currently playing note.
29+
playing_index = None
30+
31+
# Helper to convert an integer to an rgb value.
32+
def rgb_from_int(rgb):
33+
b = rgb & 255
34+
g = (rgb >> 8) & 255
35+
r = (rgb >> 16) & 255
36+
return r, g, b
37+
38+
# Loop forever, until the heat death of the universe
39+
# (or we lose power, whichever comes first).
40+
while True:
41+
# To save time, we'll only update the pixels when a key event happens.
42+
update_pixels = False
43+
44+
# Process all pending events.
45+
while macropad.keys.events:
46+
key_event = macropad.keys.events.get()
47+
48+
# We need to update the pixels again at the end of the main loop.
49+
update_pixels = True
50+
51+
if key_event.pressed:
52+
# Append pressed key to the end of the stack
53+
key_pressed_stack.append(key_event.key_number)
54+
else:
55+
# Remove released key from the stack
56+
key_pressed_stack.remove(key_event.key_number)
57+
58+
# Turn this pixel off since the key is no longer pressed.
59+
macropad.pixels[key_event.key_number] = 0
60+
61+
# How many keys are currently pressed?
62+
pressed_count = len(key_pressed_stack)
63+
64+
# There are some keys pressed.
65+
if pressed_count > 0:
66+
# Get the most recently pressed key
67+
top_index = key_pressed_stack[pressed_count - 1]
68+
69+
# If the most recently pressed key's tone isn't already playing;
70+
if top_index != playing_index:
71+
# If a tone was playing, stop it, so we can play the next one.
72+
if playing_index is not None:
73+
macropad.stop_tone()
74+
75+
# Play this key's tone and remember which one it is.
76+
macropad.start_tone(tones[top_index])
77+
playing_index = top_index
78+
79+
# There are no keys pressed.
80+
else:
81+
# If a tone was playing, stop it.
82+
if playing_index is not None:
83+
macropad.stop_tone()
84+
playing_index = None
85+
86+
# If a key was pressed or released, update the pixels for the pressed keys.
87+
if update_pixels:
88+
for key_index in key_pressed_stack:
89+
# Get the color for this key.
90+
wheel_color = colorwheel(int(255 / 12) * key_index)
91+
92+
if key_index == playing_index:
93+
# Show the currently playing key at full brightness.
94+
macropad.pixels[key_index] = wheel_color
95+
else:
96+
# Dim the rest of the keys to 10% brightness.
97+
(r, g, b) = rgb_from_int(wheel_color)
98+
macropad.pixels[key_index] = (r * 0.1, g * 0.1, b * 0.1)
99+
100+
# Don't forget to show the pixels!
101+
macropad.pixels.show()
102+

0 commit comments

Comments
 (0)