Code:
/*
A pushbutton (ordinary momentary type) needs to be connected
between pin 8 and GND. Serial1 TX and RX are connected with a
470R resistor.
You must select MIDIx4 from the "Tools > USB Type" menu
Each time a button is pressed, send another usbMIDI message
concurrently on the primaryCable and Serial1 TX.
Serial1 RX is decoded and re-sent on loopedCable.
This very long example demonstrates all possible usbMIDI
and Serial Midi message send functions. It's mostly meant
for testing and as a reference to easily copy-and-paste
the code for every message send function.
This example code is in the public domain.
*/
#include <MIDI.h>
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI);
#include <Bounce.h>
// the MIDI channel number to send messages
const int channel = 1;
// the MIDI virtual cable to use
int primaryCable = 0;
int loopedCable = 1;
// Create a Bounce object for the button.
const int pin = 47;
Bounce button1 = Bounce(pin, 10);
// remember when a note-on message has been sent
int note = 0;
// which message will we do next
int state = 0;
// sysex message to send
uint8_t buf[] = {0xF0, 6, 24, 64, 5, 1, 0xF7};
void setup() {
pinMode(pin, INPUT_PULLUP);
MIDI.begin();
MIDI.turnThruOff();// To prevent Midi feedback
MIDI.setHandleNoteOff(myNoteOff);
MIDI.setHandleNoteOn(myNoteOn);
MIDI.setHandleAfterTouchPoly(myAfterTouchPoly);
MIDI.setHandleControlChange(myControlChange);
MIDI.setHandleProgramChange(myProgramChange);
MIDI.setHandleAfterTouchChannel(myAfterTouchChannel);
MIDI.setHandlePitchBend(myPitchBend);
MIDI.setHandleSystemExclusive(mySystemExclusive);
MIDI.setHandleClock(myClock);
MIDI.setHandleStart(myStart);
MIDI.setHandleContinue(myContinue);
MIDI.setHandleStop(myStop);
MIDI.setHandleActiveSensing(myActiveSensing);
MIDI.setHandleSystemReset(mySystemReset);
MIDI.setHandleTimeCodeQuarterFrame(myTimeCodeQuarterFrame);
MIDI.setHandleTuneRequest(myTuneRequest);
MIDI.setHandleSongPosition(mySongPosition);
MIDI.setHandleSongSelect(mySongSelect);
}
void loop() {
while (MIDI.read()) {
// controllers must call .read() to keep the queue clear even if they are not responding to MIDI
}
while (usbMIDI.read()) {
// ignore incoming messages
}
button1.update();
if (button1.fallingEdge()) {
// when the button is pressed, send another message
sendNextMessage();
}
if (button1.risingEdge()) {
// when the button is release, send note off if we left a note on
if (note > 0) {
usbMIDI.sendNoteOff(note, 0, channel, primaryCable);
MIDI.sendNoteOff(note, 0, channel);
note = 0;
}
}
}
void sendNextMessage() {
switch (state) {
case 0:
note = analogRead(A0) / 8;
if (note == 0) note = 1;
usbMIDI.sendNoteOn(note, 99, channel, primaryCable);
MIDI.sendNoteOn(note, 99, channel);
break;
case 1:
usbMIDI.sendAfterTouchPoly(65, 110, channel, primaryCable);
MIDI.sendAfterTouch(65, 110, channel);
break;
case 2:
usbMIDI.sendControlChange(7, 100, channel, primaryCable);
MIDI.sendControlChange(7, 100, channel);
break;
case 3:
usbMIDI.sendProgramChange(2, channel, primaryCable);
MIDI.sendProgramChange(2, channel);
break;
case 4:
usbMIDI.sendAfterTouch(108, channel, primaryCable);
MIDI.sendAfterTouch(108, channel);
break;
case 5:
usbMIDI.sendPitchBend(911, channel, primaryCable);
MIDI.sendPitchBend(911, channel);
break;
case 6:
usbMIDI.sendSysEx(sizeof(buf), buf, true, primaryCable);
MIDI.sendSysEx(sizeof(buf), buf, true);
break;
case 7:
usbMIDI.sendSysEx(sizeof(buf) - 2, buf + 1, false, primaryCable);
MIDI.sendSysEx(sizeof(buf) - 2, buf + 1, false);
break;
case 8:
usbMIDI.sendRealTime(usbMIDI.Clock, primaryCable);
MIDI.sendClock();
break;
case 9:
usbMIDI.sendRealTime(usbMIDI.Start, primaryCable);
MIDI.sendStart();
break;
case 10:
usbMIDI.sendRealTime(usbMIDI.Continue, primaryCable);
MIDI.sendContinue();
break;
case 11:
usbMIDI.sendRealTime(usbMIDI.Stop, primaryCable);
MIDI.sendStop();
break;
case 12:
usbMIDI.sendRealTime(usbMIDI.ActiveSensing, primaryCable);
MIDI.sendActiveSensing();
break;
case 13:
usbMIDI.sendRealTime(usbMIDI.SystemReset, primaryCable);
MIDI.sendSystemReset();
break;
case 14:
usbMIDI.sendTimeCodeQuarterFrame(0, 3, primaryCable);
usbMIDI.sendTimeCodeQuarterFrame(1, 1, primaryCable);
usbMIDI.sendTimeCodeQuarterFrame(2, 7, primaryCable);
usbMIDI.sendTimeCodeQuarterFrame(3, 4, primaryCable);
usbMIDI.sendTimeCodeQuarterFrame(4, 1, primaryCable);
usbMIDI.sendTimeCodeQuarterFrame(5, 1, primaryCable);
usbMIDI.sendTimeCodeQuarterFrame(6, 0, primaryCable);
usbMIDI.sendTimeCodeQuarterFrame(7, 0, primaryCable);
/*
Commented out as these messages are actually sent
on usbMIDI primaryCable
MIDI.sendTimeCodeQuarterFrame(0, 3);
MIDI.sendTimeCodeQuarterFrame(1, 1);
MIDI.sendTimeCodeQuarterFrame(2, 7);
MIDI.sendTimeCodeQuarterFrame(3, 4);
MIDI.sendTimeCodeQuarterFrame(4, 1);
MIDI.sendTimeCodeQuarterFrame(5, 1);
MIDI.sendTimeCodeQuarterFrame(6, 0);
MIDI.sendTimeCodeQuarterFrame(7, 0);
*/
break;
case 15:
usbMIDI.sendTuneRequest(primaryCable);
MIDI.sendTuneRequest();
break;
case 16:
usbMIDI.sendSongPosition(2531, primaryCable);
MIDI.sendSongPosition(2531);
break;
case 17:
usbMIDI.sendSongSelect(107, primaryCable);
MIDI.sendSongSelect(107);
break;
case 18:
usbMIDI.beginRpn(1, channel, primaryCable);
usbMIDI.sendRpnValue(6489, channel, primaryCable);
usbMIDI.endRpn(channel, primaryCable);
MIDI.beginRpn(1, channel);
MIDI.sendRpnValue(6489, channel);
MIDI.endRpn(channel);
break;
case 19:
usbMIDI.beginRpn(1, channel, primaryCable);
usbMIDI.sendRpnIncrement(14, channel, primaryCable);
usbMIDI.endRpn(channel, primaryCable);
MIDI.beginRpn(1, channel);
MIDI.sendRpnIncrement(14, channel);
MIDI.endRpn(channel);
break;
case 20:
usbMIDI.beginRpn(1, channel, primaryCable);
usbMIDI.sendRpnDecrement(9, channel, primaryCable);
usbMIDI.endRpn(channel, primaryCable);
MIDI.beginRpn(1, channel);
MIDI.sendRpnDecrement(9, channel);
MIDI.endRpn(channel);
break;
case 21:
usbMIDI.beginNrpn(417, channel, primaryCable);
usbMIDI.sendRpnValue(6489, channel, primaryCable);
usbMIDI.endRpn(channel, primaryCable);
MIDI.beginNrpn(417, channel);
MIDI.sendRpnValue(6489, channel);
MIDI.endRpn(channel);
break;
case 22:
usbMIDI.beginNrpn(417, channel, primaryCable);
usbMIDI.sendRpnIncrement(3, channel, primaryCable);
usbMIDI.endRpn(channel, primaryCable);
MIDI.beginNrpn(417, channel);
MIDI.sendRpnIncrement(3, channel);
MIDI.endRpn(channel);
break;
case 23:
usbMIDI.beginNrpn(417, channel, primaryCable);
usbMIDI.sendRpnDecrement(2, channel, primaryCable);
usbMIDI.endRpn(channel, primaryCable);
MIDI.beginNrpn(417, channel);
MIDI.sendRpnDecrement(2, channel);
MIDI.endRpn(channel);
break;
}
state = state + 1;
if (state > 23) state = 0;
}
//******************* Handlers **************************************
void myNoteOff(byte channel, byte note, byte velocity) {
usbMIDI.sendNoteOff(note, velocity, channel, loopedCable);
}
void myNoteOn(byte channel, byte note, byte velocity) {
usbMIDI.sendNoteOn(note, velocity, channel, loopedCable);
}
void myAfterTouchPoly(byte channel, byte note, byte velocity) {
usbMIDI.sendAfterTouchPoly(note, velocity, channel, loopedCable);
}
void myControlChange(byte channel, byte control, byte value) {
usbMIDI.sendControlChange(control, value, channel, loopedCable);
}
void myProgramChange(byte channel, byte program) {
usbMIDI.sendProgramChange(program, channel, loopedCable);
}
void myAfterTouchChannel(byte channel, byte pressure) {
usbMIDI.sendAfterTouch(pressure, channel, loopedCable);
}
void myPitchBend(byte channel, int pitch) {
usbMIDI.sendPitchBend(pitch, channel, loopedCable);
}
void mySystemExclusive(const byte *data, uint16_t length) {
usbMIDI.sendSysEx( length, data, true, loopedCable);
}
void myClock() {
usbMIDI.sendRealTime(usbMIDI.Clock, loopedCable);
}
void myStart() {
usbMIDI.sendRealTime(usbMIDI.Start, loopedCable);
}
void myContinue() {
usbMIDI.sendRealTime(usbMIDI.Continue, loopedCable);
}
void myStop() {
usbMIDI.sendRealTime(usbMIDI.Stop, loopedCable);
}
void myActiveSensing() {
usbMIDI.sendRealTime(usbMIDI.ActiveSensing, loopedCable);
}
void mySystemReset() {
usbMIDI.sendRealTime(usbMIDI.SystemReset, loopedCable);
}
void myTimeCodeQuarterFrame(byte data) {
usbMIDI.sendTimeCodeQuarterFrame(data, loopedCable);
}
void myTuneRequest() {
usbMIDI.sendTuneRequest(loopedCable);
}
// needed unsigned to remove compiler warning
void mySongPosition(unsigned beats) {
usbMIDI.sendSongPosition(beats, loopedCable);
}
void mySongSelect(byte songNumber) {
usbMIDI.sendSongSelect(songNumber, loopedCable);
}
WRT line 160, dunno if I've missed something obvious or what with Midi TimeCode, not needed to use it yet.