You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
6.8 KiB
183 lines
6.8 KiB
1 year ago
|
/* Create a "class compliant " USB to 6 MIDI IN and 6 MIDI OUT interface,
|
||
|
plus 10 more USB connected devices. Admittedly, you could just plug
|
||
|
those 10 devices directly into your computer, but this example is meant
|
||
|
to show how to forward any MIDI message between the 3 different MIDI
|
||
|
libraries. A "real" application might do something more interesting,
|
||
|
like translate or modify the MIDI messages....
|
||
|
|
||
|
MIDI receive (6N138 optocoupler) input circuit and series resistor
|
||
|
outputs need to be connected to Serial1-Serial6. A USB host cable
|
||
|
is needed on Teensy 3.6's second USB port, and obviously USB hubs
|
||
|
are needed to connect up to 10 USB MIDI devices. That's a *LOT* of
|
||
|
extra hardware to connect to a Teensy!
|
||
|
|
||
|
You must select MIDIx16 from the "Tools > USB Type" menu
|
||
|
|
||
|
This example code is in the public domain.
|
||
|
*/
|
||
|
|
||
|
#include <MIDI.h> // access to serial (5 pin DIN) MIDI
|
||
|
#include <USBHost_t36.h> // access to USB MIDI devices (plugged into 2nd USB port)
|
||
|
|
||
|
// Create the Serial MIDI ports
|
||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI1);
|
||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, MIDI2);
|
||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial3, MIDI3);
|
||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial4, MIDI4);
|
||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial5, MIDI5);
|
||
|
MIDI_CREATE_INSTANCE(HardwareSerial, Serial6, MIDI6);
|
||
|
//midi::MidiInterface &SerialMidiList[6] = {MIDI1, MIDI2, MIDI3, MIDI4, MIDI5, MIDI6};
|
||
|
|
||
|
// Create the ports for USB devices plugged into Teensy's 2nd USB port (via hubs)
|
||
|
USBHost myusb;
|
||
|
USBHub hub1(myusb);
|
||
|
USBHub hub2(myusb);
|
||
|
USBHub hub3(myusb);
|
||
|
USBHub hub4(myusb);
|
||
|
MIDIDevice midi01(myusb);
|
||
|
MIDIDevice midi02(myusb);
|
||
|
MIDIDevice midi03(myusb);
|
||
|
MIDIDevice midi04(myusb);
|
||
|
MIDIDevice midi05(myusb);
|
||
|
MIDIDevice midi06(myusb);
|
||
|
MIDIDevice midi07(myusb);
|
||
|
MIDIDevice midi08(myusb);
|
||
|
MIDIDevice midi09(myusb);
|
||
|
MIDIDevice midi10(myusb);
|
||
|
MIDIDevice * midilist[10] = {
|
||
|
&midi01, &midi02, &midi03, &midi04, &midi05, &midi06, &midi07, &midi08, &midi09, &midi10
|
||
|
};
|
||
|
|
||
|
// A variable to know how long the LED has been turned on
|
||
|
elapsedMillis ledOnMillis;
|
||
|
|
||
|
|
||
|
void setup() {
|
||
|
Serial.begin(115200);
|
||
|
pinMode(13, OUTPUT); // LED pin
|
||
|
digitalWrite(13, LOW);
|
||
|
MIDI1.begin(MIDI_CHANNEL_OMNI);
|
||
|
MIDI2.begin(MIDI_CHANNEL_OMNI);
|
||
|
MIDI3.begin(MIDI_CHANNEL_OMNI);
|
||
|
MIDI4.begin(MIDI_CHANNEL_OMNI);
|
||
|
MIDI5.begin(MIDI_CHANNEL_OMNI);
|
||
|
MIDI6.begin(MIDI_CHANNEL_OMNI);
|
||
|
// Wait 1.5 seconds before turning on USB Host. If connected USB devices
|
||
|
// use too much power, Teensy at least completes USB enumeration, which
|
||
|
// makes isolating the power issue easier.
|
||
|
delay(1500);
|
||
|
Serial.println("Interface_16x16 Example");
|
||
|
delay(10);
|
||
|
myusb.begin();
|
||
|
}
|
||
|
|
||
|
|
||
|
void loop() {
|
||
|
bool activity = false;
|
||
|
|
||
|
// First read messages from the 6 Serial MIDI IN ports
|
||
|
if (MIDI1.read()) {
|
||
|
sendToComputer(MIDI1.getType(), MIDI1.getData1(), MIDI1.getData2(), MIDI1.getChannel(), MIDI1.getSysExArray(), 0);
|
||
|
activity = true;
|
||
|
}
|
||
|
if (MIDI2.read()) {
|
||
|
sendToComputer(MIDI2.getType(), MIDI2.getData1(), MIDI2.getData2(), MIDI2.getChannel(), MIDI2.getSysExArray(), 1);
|
||
|
activity = true;
|
||
|
}
|
||
|
if (MIDI3.read()) {
|
||
|
sendToComputer(MIDI3.getType(), MIDI3.getData1(), MIDI3.getData2(), MIDI3.getChannel(), MIDI3.getSysExArray(), 2);
|
||
|
activity = true;
|
||
|
}
|
||
|
if (MIDI4.read()) {
|
||
|
sendToComputer(MIDI4.getType(), MIDI4.getData1(), MIDI4.getData2(), MIDI4.getChannel(), MIDI4.getSysExArray(), 3);
|
||
|
activity = true;
|
||
|
}
|
||
|
if (MIDI5.read()) {
|
||
|
sendToComputer(MIDI5.getType(), MIDI5.getData1(), MIDI5.getData2(), MIDI5.getChannel(), MIDI5.getSysExArray(), 4);
|
||
|
activity = true;
|
||
|
}
|
||
|
if (MIDI6.read()) {
|
||
|
sendToComputer(MIDI6.getType(), MIDI6.getData1(), MIDI6.getData2(), MIDI6.getChannel(), MIDI6.getSysExArray(), 5);
|
||
|
activity = true;
|
||
|
}
|
||
|
|
||
|
// Next read messages arriving from the (up to) 10 USB devices plugged into the USB Host port
|
||
|
for (int port=0; port < 10; port++) {
|
||
|
if (midilist[port]->read()) {
|
||
|
uint8_t type = midilist[port]->getType();
|
||
|
uint8_t data1 = midilist[port]->getData1();
|
||
|
uint8_t data2 = midilist[port]->getData2();
|
||
|
uint8_t channel = midilist[port]->getChannel();
|
||
|
const uint8_t *sys = midilist[port]->getSysExArray();
|
||
|
sendToComputer(type, data1, data2, channel, sys, 6 + port);
|
||
|
activity = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Finally, read any messages the PC sends to Teensy, and forward them
|
||
|
// to either Serial MIDI or to USB devices on the USB host port.
|
||
|
if (usbMIDI.read()) {
|
||
|
// get the USB MIDI message, defined by these 5 numbers (except SysEX)
|
||
|
byte type = usbMIDI.getType();
|
||
|
byte channel = usbMIDI.getChannel();
|
||
|
byte data1 = usbMIDI.getData1();
|
||
|
byte data2 = usbMIDI.getData2();
|
||
|
byte cable = usbMIDI.getCable();
|
||
|
|
||
|
// forward this message to 1 of the 3 Serial MIDI OUT ports
|
||
|
if (type != usbMIDI.SystemExclusive) {
|
||
|
// Normal messages, first we must convert usbMIDI's type (an ordinary
|
||
|
// byte) to the MIDI library's special MidiType.
|
||
|
midi::MidiType mtype = (midi::MidiType)type;
|
||
|
|
||
|
// Then simply give the data to the MIDI library send()
|
||
|
switch (cable) {
|
||
|
case 0: MIDI1.send(mtype, data1, data2, channel); break;
|
||
|
case 1: MIDI2.send(mtype, data1, data2, channel); break;
|
||
|
case 2: MIDI3.send(mtype, data1, data2, channel); break;
|
||
|
case 3: MIDI4.send(mtype, data1, data2, channel); break;
|
||
|
case 4: MIDI5.send(mtype, data1, data2, channel); break;
|
||
|
case 5: MIDI6.send(mtype, data1, data2, channel); break;
|
||
|
default: // cases 6-15
|
||
|
midilist[cable - 6]->send(type, data1, data2, channel);
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
// SysEx messages are special. The message length is given in data1 & data2
|
||
|
unsigned int SysExLength = data1 + data2 * 256;
|
||
|
switch (cable) {
|
||
|
case 0: MIDI1.sendSysEx(SysExLength, usbMIDI.getSysExArray(), true); break;
|
||
|
case 1: MIDI2.sendSysEx(SysExLength, usbMIDI.getSysExArray(), true); break;
|
||
|
case 2: MIDI3.sendSysEx(SysExLength, usbMIDI.getSysExArray(), true); break;
|
||
|
case 3: MIDI4.sendSysEx(SysExLength, usbMIDI.getSysExArray(), true); break;
|
||
|
case 4: MIDI5.sendSysEx(SysExLength, usbMIDI.getSysExArray(), true); break;
|
||
|
case 5: MIDI6.sendSysEx(SysExLength, usbMIDI.getSysExArray(), true); break;
|
||
|
default: // cases 6-15
|
||
|
midilist[cable - 6]->sendSysEx(SysExLength, usbMIDI.getSysExArray(), true);
|
||
|
}
|
||
|
}
|
||
|
activity = true;
|
||
|
}
|
||
|
|
||
|
// blink the LED when any activity has happened
|
||
|
if (activity) {
|
||
|
digitalWriteFast(13, HIGH); // LED on
|
||
|
ledOnMillis = 0;
|
||
|
}
|
||
|
if (ledOnMillis > 15) {
|
||
|
digitalWriteFast(13, LOW); // LED off
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
void sendToComputer(byte type, byte data1, byte data2, byte channel, const uint8_t *sysexarray, byte cable)
|
||
|
{
|
||
|
if (type != midi::SystemExclusive) {
|
||
|
usbMIDI.send(type, data1, data2, channel, cable);
|
||
|
} else {
|
||
|
unsigned int SysExLength = data1 + data2 * 256;
|
||
|
usbMIDI.sendSysEx(SysExLength, sysexarray, true, cable);
|
||
|
}
|
||
|
}
|