diff --git a/MIDI_for_Makers/BLE_MIDI_Sequencer/code.py b/MIDI_for_Makers/BLE_MIDI_Sequencer/code.py new file mode 100644 index 000000000..7998b4ca3 --- /dev/null +++ b/MIDI_for_Makers/BLE_MIDI_Sequencer/code.py @@ -0,0 +1,96 @@ +# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries +# SPDX-License-Identifier: MIT + +import time +import adafruit_ble +import touchio +import board +import adafruit_midi +import adafruit_ble_midi +from adafruit_ble.advertising.standard import ProvideServicesAdvertisement +from adafruit_midi.note_on import NoteOn +from adafruit_midi.note_off import NoteOff + +# CLUE cap touch setup +c_touch = touchio.TouchIn(board.D0) +f_touch = touchio.TouchIn(board.D1) +g_touch = touchio.TouchIn(board.D2) + +# array of touch pads +pads = [c_touch, f_touch, g_touch] + +# BLE MIDI setup +midi_service = adafruit_ble_midi.MIDIService() +advertisement = ProvideServicesAdvertisement(midi_service) + +ble = adafruit_ble.BLERadio() +if ble.connected: + for c in ble.connections: + c.disconnect() + +# midi setup +midi = adafruit_midi.MIDI(midi_out=midi_service, out_channel=0) + +print("advertising") +ble.start_advertising(advertisement) + +# MIDI note numbers for C, F and G major triads +c_triad = (60, 64, 67) +f_triad = (65, 69, 72) +g_triad = (67, 71, 74) + +# array of triads +triads = [c_triad, f_triad, g_triad] + +# touch debounce states +c_pressed = False +f_pressed = False +g_pressed = False + +# array of debounce states +triad_states = [c_pressed, f_pressed, g_pressed] + +# beginning triad +active_triad = c_triad +# variable for triad index +z = 0 + +while True: + # BLE connection + print("Waiting for connection") + while not ble.connected: + pass + print("Connected") + time.sleep(1.0) + + # while BLE is connected... + while ble.connected: + # iterate through the touch inputs + for i in range(3): + inputs = pads[i] + # if a touch input is detected... + if inputs.value and triad_states[i] is False: + # debounce state activated + triad_states[i] = True + # update triad + active_triad = triads[i] + print(active_triad) + # after touch input... + if not inputs.value and triad_states[i] is True: + # reset debounce state + triad_states[i] = False + # send triad arpeggios out with half second delay + midi.send(NoteOn(active_triad[z])) + time.sleep(0.5) + midi.send(NoteOff(active_triad[z])) + time.sleep(0.5) + # increase index by 1 + z += 1 + # reset index at end of triad + if z > 2: + z = 0 + + # BLE connection + print("Disconnected") + print() + ble.start_advertising(advertisement) diff --git a/MIDI_for_Makers/Basic_MIDI_Keyboard/code.py b/MIDI_for_Makers/Basic_MIDI_Keyboard/code.py new file mode 100644 index 000000000..83a155aab --- /dev/null +++ b/MIDI_for_Makers/Basic_MIDI_Keyboard/code.py @@ -0,0 +1,55 @@ +# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries +# SPDX-License-Identifier: MIT + +import board +import digitalio +import usb_midi +import adafruit_midi +from adafruit_midi.note_on import NoteOn +from adafruit_midi.note_off import NoteOff + +# midi setup +midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=0) + +# midi note numbers +midi_notes = [60, 64, 67, 72] + +# digital pins for the buttons +key_pins = [board.D5, board.D6, board.D9, board.D10] + +# array for buttons +keys = [] + +# setup buttons as inputs +for key in key_pins: + key_pin = digitalio.DigitalInOut(key) + key_pin.direction = digitalio.Direction.INPUT + key_pin.pull = digitalio.Pull.UP + keys.append(key_pin) + +# states for buttons +key0_pressed = False +key1_pressed = False +key2_pressed = False +key3_pressed = False + +# array for button states +key_states = [key0_pressed, key1_pressed, key2_pressed, key3_pressed] + +while True: + + # iterate through 4 buttons + for i in range(4): + inputs = keys[i] + # if button is pressed... + if not inputs.value and key_states[i] is False: + # update button state + key_states[i] = True + # send NoteOn for corresponding MIDI note + midi.send(NoteOn(midi_notes[i], 120)) + + # if the button is released... + if inputs.value and key_states[i] is True: + # send NoteOff for corresponding MIDI note + midi.send(NoteOff(midi_notes[i], 120)) + key_states[i] = False diff --git a/MIDI_for_Makers/Control_Motors_with_MIDI/code.py b/MIDI_for_Makers/Control_Motors_with_MIDI/code.py new file mode 100644 index 000000000..18046f14a --- /dev/null +++ b/MIDI_for_Makers/Control_Motors_with_MIDI/code.py @@ -0,0 +1,35 @@ +# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries +# SPDX-License-Identifier: MIT + +import board +import pwmio +import usb_midi +import adafruit_midi +from adafruit_midi.note_off import NoteOff +from adafruit_midi.note_on import NoteOn +from adafruit_motor import servo + +# pwm setup for servo +pwm = pwmio.PWMOut(board.D2, duty_cycle=2 ** 15, frequency=50) + +# servo setup +motor = servo.Servo(pwm) + +# midi setup +midi = adafruit_midi.MIDI( + midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0 +) + +while True: + # receive midi input + msg = midi.receive() + + if msg is not None: + # if a NoteOn message is received... + if isinstance(msg, NoteOn): + # servo set to 180 degrees + motor.angle = 180 + # if a NoteOff message is received... + if isinstance(msg, NoteOff): + # servo set to 0 degrees + motor.angle = 0 diff --git a/MIDI_for_Makers/MIDI_CC_Control_with_Pots/code.py b/MIDI_for_Makers/MIDI_CC_Control_with_Pots/code.py new file mode 100644 index 000000000..a33bcc567 --- /dev/null +++ b/MIDI_for_Makers/MIDI_CC_Control_with_Pots/code.py @@ -0,0 +1,82 @@ +# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries +# SPDX-License-Identifier: MIT + +import board +import usb_midi +import adafruit_midi +import simpleio +from analogio import AnalogIn +from adafruit_midi.control_change import ControlChange +from adafruit_midi.pitch_bend import PitchBend + +# midi setup +midi = adafruit_midi.MIDI( + midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0 +) + +# potentiometer setup +mod_pot = AnalogIn(board.A0) +pitchDown_pot = AnalogIn(board.A1) +pitchUp_pot = AnalogIn(board.A2) +sus_pot = AnalogIn(board.A3) + +# function to read analog input +def val(pin): + return pin.value + +# variables for last read value +# defaults to 0 +# no pitchbend is 8192 +mod_val2 = 0 +pitchDown_val2 = 8192 +pitchUp_val2 = 8192 +sus_val2 = 0 + +while True: + + # map range of analog input to midi values + # pitchbend range is 0 to 16383 with 8192 centered or no pitchbend + mod_val1 = round(simpleio.map_range(val(mod_pot), 0, 65535, 0, 127)) + pitchDown_val1 = round(simpleio.map_range(val(pitchDown_pot), 0, 65535, 0, 8192)) + pitchUp_val1 = round(simpleio.map_range(val(pitchUp_pot), 0, 65535, 8192, 16383)) + sus_val1 = round(simpleio.map_range(val(sus_pot), 0, 65535, 0, 127)) + + # if modulation value is updated... + if abs(mod_val1 - mod_val2) > 2: + # update mod_val2 + mod_val2 = mod_val1 + # create integer + modulation = int(mod_val2) + # create CC message + modWheel = ControlChange(1, modulation) + # send CC message + midi.send(modWheel) + + # pitchbend down value is updated... + if abs(pitchDown_val1 - pitchDown_val2) > 75: + # update pitchDown_val2 + pitchDown_val2 = pitchDown_val1 + # create PitchBend message + pitchDown = PitchBend(int(pitchDown_val2)) + # send PitchBend message + midi.send(pitchDown) + + # pitchbend up value is updated... + if abs(pitchUp_val1 - pitchUp_val2) > 75: + # updated pitchUp_val2 + pitchUp_val2 = pitchUp_val1 + # create PitchBend message + pitchUp = PitchBend(int(pitchUp_val2)) + # send PitchBend message + midi.send(pitchUp) + + # sustain value is updated... + if abs(sus_val1 - sus_val2) > 2: + # update sus_val2 + sus_val2 = sus_val1 + # create integer + sustain = int(sus_val2) + # create CC message + sustainPedal = ControlChange(64, sustain) + # send CC message + midi.send(sustainPedal) diff --git a/MIDI_for_Makers/Receive_MIDI_Over_UART_and_Send_Over_USB/code.py b/MIDI_for_Makers/Receive_MIDI_Over_UART_and_Send_Over_USB/code.py new file mode 100644 index 000000000..0b27830ec --- /dev/null +++ b/MIDI_for_Makers/Receive_MIDI_Over_UART_and_Send_Over_USB/code.py @@ -0,0 +1,47 @@ +# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries +# SPDX-License-Identifier: MIT + +import board +import busio +import adafruit_midi +import usb_midi +from adafruit_midi.control_change import ControlChange +from adafruit_midi.pitch_bend import PitchBend +from adafruit_midi.note_off import NoteOff +from adafruit_midi.note_on import NoteOn + +# uart setup +uart = busio.UART(board.TX, board.RX, baudrate=31250) +# midi channel setup +midi_in_channel = 1 +midi_out_channel = 1 +# midi setup +# UART is setup as the input +# USB is setup as the output +midi = adafruit_midi.MIDI( + midi_in=uart, + midi_out=usb_midi.ports[1], + in_channel=(midi_in_channel - 1), + out_channel=(midi_out_channel - 1), + debug=False, +) + +print("MIDI UART In/USB Out") +print("Default output channel:", midi.out_channel + 1) + +# array of message types +messages = (NoteOn, NoteOff, PitchBend, ControlChange) + +while True: + # receive MIDI input from UART + msg = midi.receive() + + # if the input is a recognized message... + if msg is not None: + for i in range(0, 3): + # iterate through message types + # makes it so that you aren't sending any unnecessary messages + if isinstance(msg, messages[i]): + # send the input out via USB + midi.send(msg) + print(msg) diff --git a/MIDI_for_Makers/Receive_and_Display_MIDI_Messages/code.py b/MIDI_for_Makers/Receive_and_Display_MIDI_Messages/code.py new file mode 100644 index 000000000..03c6ab764 --- /dev/null +++ b/MIDI_for_Makers/Receive_and_Display_MIDI_Messages/code.py @@ -0,0 +1,76 @@ +# SPDX-FileCopyrightText: 2022 Liz Clark for Adafruit Industries +# SPDX-License-Identifier: MIT + +import board +import busio +import usb_midi +import adafruit_midi +import displayio +import terminalio +from adafruit_display_text import label +import adafruit_displayio_ssd1306 +from adafruit_midi.control_change import ControlChange +from adafruit_midi.note_off import NoteOff +from adafruit_midi.note_on import NoteOn +from adafruit_midi.pitch_bend import PitchBend + +displayio.release_displays() + +oled_reset = board.D1 + +# I2C setup for display +i2c = busio.I2C(board.SCL1, board.SDA1) +display_bus = displayio.I2CDisplay(i2c, device_address=0x3D, reset=oled_reset) + +# midi setup +print(usb_midi.ports) +midi = adafruit_midi.MIDI( + midi_in=usb_midi.ports[0], in_channel=0, midi_out=usb_midi.ports[1], out_channel=0 +) + +msg = midi.receive() + +# display width and height setup +WIDTH = 128 +HEIGHT = 32 +BORDER = 5 + +# display setup +display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=WIDTH, height=HEIGHT) + +splash = displayio.Group() +display.show(splash) + +# text area setup +text = "MIDI Messages" +text_area = label.Label( + terminalio.FONT, text=text, color=0xFFFFFF, x=28, y=HEIGHT // 2+1) +splash.append(text_area) + +while True: + # receive midi messages + msg = midi.receive() + + if msg is not None: + # if a NoteOn message... + if isinstance(msg, NoteOn): + string_msg = 'NoteOn' + # get note number + string_val = str(msg.note) + # if a NoteOff message... + if isinstance(msg, NoteOff): + string_msg = 'NoteOff' + # get note number + string_val = str(msg.note) + # if a PitchBend message... + if isinstance(msg, PitchBend): + string_msg = 'PitchBend' + # get value of pitchbend + string_val = str(msg.pitch_bend) + # if a CC message... + if isinstance(msg, ControlChange): + string_msg = 'ControlChange' + # get CC message number + string_val = str(msg.control) + # update text area with message type and value of message as strings + text_area.text = (string_msg + " " + string_val)