Skip to content

Commit 5883c9e

Browse files
committed
fix up hwtest/code.py a little
1 parent 5ec10a2 commit 5883c9e

File tree

1 file changed

+51
-42
lines changed

1 file changed

+51
-42
lines changed

circuitpython/hwtest/code.py

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# pico_test_synth_hwtest_code.py -- test hardware of pico_test_synth board
22
# 27 Jun 2023 - 15 Feb 2024 - @todbot / Tod Kurt
3+
# 3 May 2025 - updated for CircuitPython 10
34
#
45
# Functionality:
56
# - touch pads to trigger synth notes (defined in 'midi_notes')
@@ -29,9 +30,14 @@
2930
import touchio
3031
from adafruit_debouncer import Debouncer
3132
import usb_midi
32-
33-
#midi_notes = (33, 45, 52, 57)
34-
midi_notes = list(range(45,45+16))
33+
import adafruit_midi
34+
from adafruit_midi.note_on import NoteOn
35+
from adafruit_midi.note_off import NoteOff
36+
from adafruit_midi.control_change import ControlChange
37+
38+
SAMPLE_RATE = 28000
39+
BUFFER_SIZE = 4096 # need a bigger buffer when screen updated
40+
midi_notes = list(range(48,48+16)) # which MIDI notes the touch pads send
3541
filter_freq = 4000
3642
filter_resonance = 1.2
3743
output_volume = 1.0
@@ -72,26 +78,27 @@
7278
touchs.append(Debouncer(touchin))
7379

7480
print("starting up...")
75-
midi_in_usb = usb_midi.ports[0]
76-
midi_in_uart = busio.UART(rx=uart_rx_pin, tx=uart_tx_pin, baudrate=31250, timeout=0.001)
7781
i2c = busio.I2C(scl=i2c_scl_pin, sda=i2c_sda_pin, frequency=1_000_000)
82+
uart = busio.UART(rx=uart_rx_pin, tx=uart_tx_pin, baudrate=31250, timeout=0.001)
83+
midi_uart = adafruit_midi.MIDI(midi_in=uart, midi_out=uart)
84+
midi_usb = adafruit_midi.MIDI(midi_in=usb_midi.ports[0], midi_out=usb_midi.ports[1])
7885

7986
dw,dh = 128, 64
8087
display_bus = i2cdisplaybus.I2CDisplayBus(i2c, device_address=0x3c)
8188
display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=dw, height=dh, rotation=180)
8289

8390
# set up the synth->audio system
8491
audio = audiobusio.I2SOut(bit_clock=i2s_bclk_pin, word_select=i2s_lclk_pin, data=i2s_data_pin)
85-
mixer = audiomixer.Mixer(voice_count=1, sample_rate=28000, channel_count=1,
92+
mixer = audiomixer.Mixer(voice_count=1, sample_rate=SAMPLE_RATE, channel_count=1,
8693
bits_per_sample=16, samples_signed=True,
87-
buffer_size=4096) # buffer_size=4096) # need a big buffer when screen updated
88-
synth = synthio.Synthesizer(sample_rate=28000)
94+
buffer_size=BUFFER_SIZE)
95+
synth = synthio.Synthesizer(sample_rate=SAMPLE_RATE)
8996
audio.play(mixer)
9097
mixer.voice[0].level = output_volume
9198
mixer.voice[0].play(synth)
9299

93100
# set up the synth
94-
wave_saw = np.linspace(20000,-20000, num=512, dtype=np.int16) # default squ is too clippy
101+
wave_saw = np.linspace(32000,-32000, num=256, dtype=np.int16) # default squ is too clippy
95102
#amp_env = synthio.Envelope(attack_level=1.0, sustain_level=1.0, release_time=0.4, attack_time=0.4, decay_time=0.5)
96103
amp_env = synthio.Envelope(release_time=0.3, attack_time=0.3)
97104
synth.envelope = amp_env
@@ -106,25 +113,35 @@
106113
maingroup.append(t)
107114
time.sleep(1)
108115

109-
touch_notes = [None] * len(midi_notes)
116+
notes_pressed = {}
110117
sw_pressed = False
111118

119+
def note_on(midi_note):
120+
print("note_on:", midi_note)
121+
note_off(midi_note) # only one note per midi_note allowed
122+
f = synthio.midi_to_hz(midi_note)
123+
filter = synthio.Biquad(synthio.FilterMode.LOW_PASS, filter_freq, filter_resonance)
124+
n = synthio.Note(frequency=f, waveform=wave_saw, filter=filter, amplitude=0.75)
125+
synth.press( n )
126+
notes_pressed[midi_note] = n
127+
128+
def note_off(midi_note):
129+
if n := notes_pressed.get(midi_note,None):
130+
synth.release(n)
131+
132+
# check the touch pads and trigger synthio notes
112133
def check_touch():
113134
for i in range(len(touchs)):
114135
touch = touchs[i]
115136
touch.update()
116137
if touch.rose:
117138
print("touch press",i)
118-
f = synthio.midi_to_hz(midi_notes[i])
119-
filter = synthio.Biquad(synthio.FilterMode.LOW_PASS, filter_freq, filter_resonance)
120-
n = synthio.Note(frequency=f, waveform=wave_saw, filter=filter, amplitude=0.75)
121-
synth.press( n )
122-
touch_notes[i] = n
139+
note_on(midi_notes[i])
123140
if touch.fell:
124141
print("touch release", i)
125-
if touch_notes[i]:
126-
synth.release( touch_notes[i] )
127-
142+
note_off(midi_notes[i])
143+
144+
# print to REPL current state of knobs, button, and touchpads
128145
async def debug_printer():
129146
t1_last = ""
130147
t2_last = ""
@@ -142,52 +159,44 @@ async def debug_printer():
142159
print("T:" + ''.join(["%3d " % (t.raw_value//16) for t in touchins[0:4]]))
143160
await asyncio.sleep(0.3)
144161

162+
# handle all user input: knobs, button, and touchpads
145163
async def input_handler():
146-
global sw_pressed
147164
global filter_freq, filter_resonance
148165

149-
note = None
166+
midi_note = None
150167

151168
while True:
152-
filter_freq = knobA.value/65535 * 8000 + 100 # range 100-8100
169+
filter_freq = knobA.value/65535 * 8000 + 1 # range 1-8001
153170
filter_resonance = knobB.value/65535 * 3 + 0.2 # range 0.2-3.2
154171

155-
for n in touch_notes: # real-time adjustment of filter
172+
for n in notes_pressed.values(): # real-time adjustment of filter
156173
if n:
157174
n.filter.frequency = filter_freq
158175
n.filter.Q = filter_resonance
159176

160177
check_touch()
161178

162179
if key := keys.events.get():
163-
if key.released:
164-
sw_pressed = False
165-
synth.release( note )
166180
if key.pressed:
167181
sw_pressed = True
168-
f = synthio.midi_to_hz(random.randint(32,60))
169-
note = synthio.Note(frequency=f, waveform=wave_saw, amplitude=0.8)
170-
synth.press(note)
182+
midi_note = random.randint(32,60)
183+
note_on(midi_note)
184+
if key.released:
185+
sw_pressed = False
186+
note_off(midi_note)
171187
await asyncio.sleep(0.001)
172188

189+
173190
async def midi_handler():
174191
while True:
175-
while msg := midi_in_uart.read(3):
176-
print("midi in uart:", [hex(b) for b in msg])
177-
if msg[0] == 0x90: # note on
178-
synth.press( msg[1] )
179-
elif msg[0] == 0x80 or msg[0] == 0x90 and msg[2] ==0: # note off
180-
synth.release( msg[1] )
181-
182-
while msg := midi_in_usb.read(3):
183-
print("midi in usb:", [hex(b) for b in msg])
184-
if msg[0] == 0x90: # note on
185-
synth.press( msg[1] )
186-
elif msg[0] == 0x80 or msg[0] == 0x90 and msg[2] ==0: # note off
187-
synth.release( msg[1] )
188-
192+
while msg := midi_usb.receive() or midi_uart.receive():
193+
if isinstance(msg, NoteOn) and msg.velocity != 0:
194+
note_on(msg.note)
195+
elif isinstance(msg,NoteOff) or isinstance(msg,NoteOn) and msg.velocity==0:
196+
note_off(msg.note)
189197
await asyncio.sleep(0)
190198

199+
191200
# main coroutine
192201
async def main(): # Don't forget the async!
193202
task1 = asyncio.create_task(debug_printer())

0 commit comments

Comments
 (0)