diff --git a/main-micropython.py b/main-micropython.py
new file mode 100644
index 0000000..134fd0b
--- /dev/null
+++ b/main-micropython.py
@@ -0,0 +1,40 @@
+import sys
+from machine import ADC, Pin
+import pyb
+import midi
+
+# Devices
+exp = machine.ADC(31) # Expression pedal device on pin 31
+serial = pyb.USB_VCP()
+led = Pin(25, Pin.OUT)
+
+# Expression pedal settings
+exp_min = 0 # Expression pedal minimum value
+exp_max = 65535 #Expression pedal maximum value
+
+# Midi settings
+midi_channel = 1 # Target midi channel to write to
+cc = 68 # Target Control Change number - this is for Behringer X32 Matrix 5
+cc_min = 0 # Minimum desired CC output
+cc_max = 100 # Maximum desired CC output (only want fader to go to unity gain - hence not 127)
+
+# This function translates the expression pedal value to the equivalent CC value
+def translate(exp_val):
+ return (((exp_val - exp_min) * (cc_max - cc_min)) / (exp_max - exp_min)) + cc_min
+
+# Test the translate function:
+# for i in range(65535):
+# print (translate(i))
+
+usb_midi = midi.Controller(serial, channel=midi_channel)
+exp_value_previous = 0
+
+while True:
+ exp_value_current = exp.read_u16()
+ if exp_value_current != exp_value_previous:
+ led.value(1) # Turn led on
+ cc_val = translate(exp_value_current)
+ usb_midi.control_change(cc, cc_val)
+ led.value(0) # Turn led off
+ exp_value_previous = exp_value_current
+ print("Writing CC value " + cc_val)
\ No newline at end of file
diff --git a/main.py b/main.py
index 134fd0b..6d68c29 100644
--- a/main.py
+++ b/main.py
@@ -1,40 +1,37 @@
import sys
-from machine import ADC, Pin
-import pyb
-import midi
+import usb_midi
+import adafruit_midi
+from adafruit_midi.control_change import ControlChange
+import digitalio
+import analogio
+from board import *
# Devices
-exp = machine.ADC(31) # Expression pedal device on pin 31
-serial = pyb.USB_VCP()
-led = Pin(25, Pin.OUT)
+exp = analogio.AnalogIn(A0) # Expression pedal
+led = digitalio.DigitalInOut(LED)
# Expression pedal settings
exp_min = 0 # Expression pedal minimum value
exp_max = 65535 #Expression pedal maximum value
# Midi settings
-midi_channel = 1 # Target midi channel to write to
+midi_channel = 0 # Target midi channel to write to
cc = 68 # Target Control Change number - this is for Behringer X32 Matrix 5
cc_min = 0 # Minimum desired CC output
cc_max = 100 # Maximum desired CC output (only want fader to go to unity gain - hence not 127)
# This function translates the expression pedal value to the equivalent CC value
def translate(exp_val):
- return (((exp_val - exp_min) * (cc_max - cc_min)) / (exp_max - exp_min)) + cc_min
+ return int((((exp_val - exp_min) * (cc_max - cc_min)) / (exp_max - exp_min)) + cc_min)
-# Test the translate function:
-# for i in range(65535):
-# print (translate(i))
-
-usb_midi = midi.Controller(serial, channel=midi_channel)
-exp_value_previous = 0
+midi = adafruit_midi.MIDI(midi_out=usb_midi.ports[1], out_channel=midi_channel)
+cc_val_last = 0
+led.switch_to_output(value=True)
while True:
- exp_value_current = exp.read_u16()
- if exp_value_current != exp_value_previous:
- led.value(1) # Turn led on
- cc_val = translate(exp_value_current)
- usb_midi.control_change(cc, cc_val)
- led.value(0) # Turn led off
- exp_value_previous = exp_value_current
- print("Writing CC value " + cc_val)
\ No newline at end of file
+ cc_val = translate(exp.value)
+ if cc_val != cc_val_last:
+ led.switch_to_output(value=False) # Flicker led
+ midi.send(ControlChange(cc, cc_val)) # Write midi
+ led.switch_to_output(value=True)
+ cc_val_last = cc_val
\ No newline at end of file
diff --git a/midi.py b/midi.py
deleted file mode 100644
index a1d6461..0000000
--- a/midi.py
+++ /dev/null
@@ -1,224 +0,0 @@
-# Copyright (C) 2014 Craig Barnes
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-"""
-Micro Python Midi
-This module implements channel commands according to the midi specification.
-Each midi message consists of 3 bytes.
-The first byte is the sum of the command and the midi channel (1-16 > 0-F).
-the value of bytes 2 and 3 (data 1 and 2) are dependant on the command.
-command data1 data2 Description
-------- ----- ----- -----------
-0x80-0x8F Key # (0-127) Off Velocity (0-127) Note Off
-0x90-0x90 Key # (0-127) On Velocity (0-127) Note On
-0xA0-0xA0 Key # (0-127) Pressure (0-127) Poly Pressure
-0xB0-0xB0 Control # (0-127) Control Value (0-127) Control
-0xC0-0xC0 Program # (0-127) Not Used (send 0) Program Change
-0xD0-0xD0 Pressure Value (0-127) Not Used (send 0) Channel Pressure
-0xE0-0xE0 Range LSB (0-127) Range MSB (0-127) Pitch Bend
-http://www.midi.org/techspecs/midimessages.php
-"""
-
-
-class MidiInteger:
- """A midi message sends data as 7 bit values between 0 and 127."""
- def __init__(self, value):
- if 0 <= value < 2 ** 7:
- self.value = value
- else:
- raise ValueError(
- 'Invalid midi data value: {}'.format(value),
- 'A midi data value must be an integer between 0 and 127')
-
- def __repr__(self):
- return ''.format(self.value)
-
-
-class BigMidiInteger:
- """Some messages use 14 bit values, these need to be spit down to
- msb and lsb before being sent."""
- def __init__(self, value):
- if 0 <= value <= 2 ** 14:
- self.msb = value // 2 ** 7
- self.lsb = value % 2 ** 7
- else:
- raise ValueError(
- 'Invalid midi data value: {}'.format(value),
- 'A midi datavalue must be an integer between0'
- ' and {}'.format(2 ** 14))
-
- def __repr__(self):
- return ''.format(self.lsb, self.msb)
-
-
-class Controller:
- """A device that is designed to send midi messages to an external
- instrument or sequencer, is commonly referred to as a midi controller.
- http://en.wikipedia.org/wiki/MIDI_controller
- An instance of the Controller class should be considered to be a midi
- contoller in the same context.
- More than one can be created, there are no constraints. but the
- convention is to keep each controller on a separate midi port or channel.
- Usage
- =====
- The following example creates a controller on midi channel one using the
- USB Virtual Com Port device. Then sends a note on message followed by a
- note off message.
- >>> import pyb
- >>> my_controller = Controller(pyb.USB_VCP(), 1)
- >>> my_controller.note_on(65)
- >>> pyb.delay(100)
- >>> my_controller.note_off(65)
- In order to pass these midi signals on to your computers midi stack, you
- will need to disconnect your console from the Micro Python board,
- and run a serial to midi bridge utility such as ttymidi for Linux.
- Others are available for Mac and Windows.
- With your console still attached you would have seen the characters
- representing the bytes.
- The example above demonstrates the nature of midi note information.
- When a keyboard key is pressed a note_on message is sent. When the
- key is released a note off message is sent.
- An optional velocity value can also be sent, this usually controls
- the volume of the note played, but this is often used to control other
- characteristics of the sound played.
- """
- COMMANDS = (
- 0x80, # Note Off
- 0x90, # Note On
- 0xA0, # Poly Pressure
- 0xB0, # Control Change
- 0xC0, # Program Change
- 0xD0, # Mono Pressure
- 0xE0 # Pich Bend
- )
-
- def __init__(self, port, channel=1):
- self.port = port
- try:
- assert 1 <= channel <= 16
- except:
- raise ValueError('channel must be an integer between 1 & 16')
- self.channel = channel
- self.timeout = 100
-
- def __repr__(self):
- return ''.format(
- port=self.port,
- channel=self.channel)
-
- def send_message(self, command, data1, data2=0):
- """Send a midi message to the serial device."""
- if command not in self.COMMANDS:
- raise ValueError('Invalid Command: {}'.format(command))
-
- command += self.channel - 1
-
- self.port.send(command, timeout=self.timeout)
- self.port.send(MidiInteger(data1).value, timeout=self.timeout)
- self.port.send(MidiInteger(data2).value, timeout=self.timeout)
-
- def note_off(self, note, velocity=0):
- """Send a 'Note Off' message"""
- self.send_message(0x80, note, velocity)
-
- def note_on(self, note, velocity=127):
- """Send a 'Note On' message"""
- self.send_message(0x90, note, velocity)
-
- def pressure(self, value, note=None):
- """If a note value is provided then send a polyphonic pressure
- message, otherwise send a Channel (mono) pressure message."""
- if note:
- self.send_message(0xA0, note, value)
- else:
- self.send_message(0xD0, value)
-
- def control_change(self, control, value):
- """Send a control e.g. modulation or pedal message."""
- self.send_message(0xB0, control, value)
-
- def program_change(self, value, bank=None):
- """Send a program change message, include bank if provided."""
- if bank:
- bank = BigMidiInteger(bank)
- self.control_change(32, bank.lsb)
- self.control_change(0, bank.msb)
- self.send_message(0xC0, value)
-
- def pitch_bend(self, value=0x2000):
- """Send a pich bend message.
- Pich bend is a 14 bit value, centreed at 0x2000"""
- value = BigMidiInteger(value)
- self.send_message(0xE0, value.lsb, value.msb)
-
- def modulation(self, value, fine=False):
- """Send modulation control change."""
- if fine:
- value = MidiInteger(value)
- self.control_change(33, value.lsb)
- self.control_change(1, value.msb)
- else:
- self.control_change(1, value)
-
- def volume(self, value, fine=False):
- """Send volume control change."""
- if fine:
- value = BigMidiInteger(value)
- self.control_change(39, value.lsb)
- self.control_change(7, value.msb)
- else:
- self.control_change(7, value)
-
- def all_sound_off(self):
- """Switch all sounds off. """
- self.control_change(120, 0)
-
- def reset_all_controllers(self):
- """Set all controllers to their default values."""
- self.control_change(121, 0)
-
- def local_control(self, value):
- """Enable or disable local control."""
- if bool(value):
- self.control_change(122, 127)
- else:
- self.control_change(122, 0)
-
- def all_notes_off(self):
- """Send 'All Notes Off' message."""
- self.control_change(123, 0)
-
- def panic(self):
- """Reset everything and stop making noise."""
- self.all_sound_off()
- self.reset_all_controllers()
- self.all_notes_off()
-
-
-if __name__ == '__main__':
- import pyb
- serial = pyb.USB_VCP()
- instrument1 = Controller(serial, channel=1)
- accel = pyb.Accel()
- switch = pyb.Switch()
- while 1:
- while not switch():
- pyb.delay(10)
- note = accel.x()
- velocity = accel.y()
- instrument1.note_on(+(note + 65), +(velocity + 65))
- while switch():
- pyb.delay(50)
- instrument1.note_off(note + 65)
\ No newline at end of file