Skip to content

Commit 8a496b4

Browse files
authored
Merge pull request #16 from apendley/extended_tone_demo
Add extended tone demo to examples
2 parents 501721f + e0cc6ef commit 8a496b4

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 rainbowio import colorwheel
12+
from adafruit_macropad import MacroPad
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+
blue = rgb & 255
34+
green = (rgb >> 8) & 255
35+
red = (rgb >> 16) & 255
36+
return red, green, blue
37+
38+
39+
# Loop forever, until the heat death of the universe
40+
# (or we lose power, whichever comes first).
41+
while True:
42+
# To save time, we'll only update the pixels when a key event happens.
43+
update_pixels = False
44+
45+
# Process all pending events.
46+
while macropad.keys.events:
47+
key_event = macropad.keys.events.get()
48+
49+
# We need to update the pixels again at the end of the main loop.
50+
update_pixels = True
51+
52+
if key_event.pressed:
53+
# Append pressed key to the end of the stack
54+
key_pressed_stack.append(key_event.key_number)
55+
else:
56+
# Remove released key from the stack
57+
key_pressed_stack.remove(key_event.key_number)
58+
59+
# Turn this pixel off since the key is no longer pressed.
60+
macropad.pixels[key_event.key_number] = 0
61+
62+
# How many keys are currently pressed?
63+
pressed_count = len(key_pressed_stack)
64+
65+
# There are some keys pressed.
66+
if pressed_count > 0:
67+
# Get the most recently pressed key
68+
top_index = key_pressed_stack[pressed_count - 1]
69+
70+
# If the most recently pressed key's tone isn't already playing;
71+
if top_index != playing_index:
72+
# If a tone was playing, stop it, so we can play the next one.
73+
if playing_index is not None:
74+
macropad.stop_tone()
75+
76+
# Play this key's tone and remember which one it is.
77+
macropad.start_tone(tones[top_index])
78+
playing_index = top_index
79+
80+
# There are no keys pressed.
81+
else:
82+
# If a tone was playing, stop it.
83+
if playing_index is not None:
84+
macropad.stop_tone()
85+
playing_index = None
86+
87+
# If a key was pressed or released, update the pixels for the pressed keys.
88+
if update_pixels:
89+
for key_index in key_pressed_stack:
90+
# Get the color for this key.
91+
wheel_color = colorwheel(int(255 / 12) * key_index)
92+
93+
if key_index == playing_index:
94+
# Show the currently playing key at full brightness.
95+
macropad.pixels[key_index] = wheel_color
96+
else:
97+
# Dim the rest of the keys to 10% brightness.
98+
(r, g, b) = rgb_from_int(wheel_color)
99+
macropad.pixels[key_index] = (r * 0.1, g * 0.1, b * 0.1)
100+
101+
# Don't forget to show the pixels!
102+
macropad.pixels.show()

0 commit comments

Comments
 (0)