Skip to content

Commit 2ed855f

Browse files
committed
Add firmware
1 parent 72276bd commit 2ed855f

File tree

7 files changed

+169
-28
lines changed

7 files changed

+169
-28
lines changed

firmware/.flake8

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[flake8]
2+
# Ignore black styles.
3+
ignore = E501, W503, E203
4+
# Imports
5+
import-order-style = google
6+
application-import-names = nox,tests

firmware/.isort.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[settings]
2+
line_length=120
3+
multi_line_output=3

firmware/code.py

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,35 +20,18 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2121
# THE SOFTWARE.
2222

23-
import time
24-
import audioio
25-
import analogio
26-
import board
27-
import digitalio
28-
29-
button = digitalio.DigitalInOut(board.D2)
30-
button.switch_to_input(pull=digitalio.Pull.UP)
31-
gate = digitalio.DigitalInOut(board.D0)
32-
gate.switch_to_input()
33-
pitch_cv = analogio.AnalogIn(board.A4)
34-
35-
wave_file = open("honk-sound.wav", "rb")
36-
wave = audioio.WaveFile(wave_file)
37-
audio = audioio.AudioOut(board.A0)
23+
import winterbloom_bhb
3824

39-
last_button_value = False
40-
last_gate_value = False
41-
button_value = None
42-
gate_value = None
25+
bhb = winterbloom_bhb.BigHonkingButton()
26+
sample = bhb.load_sample("samples/honk.wav")
4327

4428
while True:
45-
button_value = not button.value
46-
gate_value = not gate.value
29+
if bhb.triggered:
30+
bhb.gate_out = True
31+
bhb.play(sample, pitch_cv=bhb.pitch_in)
4732

48-
if (not last_button_value and button_value) or (not last_gate_value and gate_value):
49-
print(pitch_cv.value)
50-
wave.sample_rate = int(44100 * ((pitch_cv.value / 65355) + 0.5))
51-
audio.play(wave)
52-
53-
last_button_value = button_value
54-
last_gate_value = gate_value
33+
if bhb.released:
34+
bhb.gate_out = False
35+
# Uncomment the call to stop to make the sample
36+
# stop playing as soon as you release the button.
37+
# bhb.stop()

firmware/noxfile.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import nox
2+
3+
4+
@nox.session(python="3")
5+
def blacken(session):
6+
"""Run black code formater."""
7+
session.install("black==19.3b0", "isort==4.3.21")
8+
files = ["noxfile.py", "code.py", "winterbloom_bhb"]
9+
session.run("isort", "--recursive", *files)
10+
session.run("black", *files)
11+
12+
13+
@nox.session(python="3")
14+
def lint(session):
15+
session.install("flake8==3.7.8", "black==19.3b0")
16+
files = ["noxfile.py", "code.py", "winterbloom_bhb"]
17+
session.run("black", "--check", *files)
18+
session.run("flake8", *files)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2020 Alethea Flowers for Winterbloom
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
23+
from winterbloom_bhb.bhb import BigHonkingButton
24+
25+
__all__ = ["BigHonkingButton"]

firmware/winterbloom_bhb/bhb.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2020 Alethea Flowers for Winterbloom
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
23+
import time
24+
25+
import audioio
26+
import board
27+
import digitalio
28+
import winterbloom_voltageio
29+
30+
31+
class BigHonkingButton:
32+
def __init__(self):
33+
self.pitch_settle_time = 0.001
34+
self._button = digitalio.DigitalInOut(board.BUTTON)
35+
self._button.switch_to_input(pull=digitalio.Pull.UP)
36+
self._gate_in = digitalio.DigitalInOut(board.GATE_IN)
37+
self._gate_in.switch_to_input()
38+
self._gate_out = digitalio.DigitalInOut(board.GATE_OUT)
39+
self._gate_out.switch_to_output()
40+
self._pitch_in = winterbloom_voltageio.VoltageIn.from_pin(board.PITCH_IN)
41+
self._pitch_in.direct_calibration(
42+
{64736: -2.0, 48384: -1.0, 32048: 0, 15552: 1.0, 128: 2.0}
43+
)
44+
self.audio_out = audioio.AudioOut(board.HONK_OUT)
45+
46+
self._last_gate_value = False
47+
self._last_button_value = False
48+
49+
@property
50+
def button(self):
51+
return not self._button.value
52+
53+
@property
54+
def gate_in(self):
55+
return not self._gate_in.value
56+
57+
@property
58+
def pitch_in(self):
59+
time.sleep(self.pitch_settle_time)
60+
return self._pitch_in.voltage
61+
62+
@property
63+
def gate_out(self):
64+
return self._gate_out.value
65+
66+
@gate_out.setter
67+
def gate_out(self, value):
68+
self._gate_out.value = value
69+
70+
@property
71+
def triggered(self):
72+
button_value = self.button
73+
gate_value = self.gate_in
74+
if (not self._last_button_value and button_value) or (
75+
not self._last_gate_value and gate_value
76+
):
77+
result = True
78+
else:
79+
result = False
80+
81+
self._last_button_value = button_value
82+
self._last_gate_value = gate_value
83+
84+
return result
85+
86+
@property
87+
def released(self):
88+
button_value = self.button
89+
gate_value = self.gate_in
90+
if not button_value and not gate_value:
91+
result = True
92+
else:
93+
result = False
94+
95+
return result
96+
97+
def load_sample(self, path):
98+
return audioio.WaveFile(open(path, "rb"))
99+
100+
def play(self, sample, pitch_cv=0):
101+
sample.sample_rate = int(44100 * pow(2, pitch_cv))
102+
self.audio_out.stop()
103+
self.audio_out.play(sample)
104+
105+
def stop(self):
106+
self.audio_out.stop()

0 commit comments

Comments
 (0)