mirror of
https://github.com/gdsports/USBHost_t36
synced 2024-11-24 01:52:23 -05:00
Add MIDI InputFunctions example
This commit is contained in:
parent
d169a1a387
commit
f59f8a16ef
250
examples/MIDI/InputFunctions/InputFunctions.ino
Normal file
250
examples/MIDI/InputFunctions/InputFunctions.ino
Normal file
@ -0,0 +1,250 @@
|
||||
/* Receive Incoming USB Host MIDI using functions. As usbMIDI
|
||||
reads incoming messages, handler functions are run.
|
||||
See the InputRead example for the non-function alterative.
|
||||
|
||||
This very long example demonstrates all possible handler
|
||||
functions. Most applications need only some of these.
|
||||
This example is meant to allow easy copy-and-paste of the
|
||||
desired functions.
|
||||
|
||||
Use the Arduino Serial Monitor to view the messages
|
||||
as Teensy receives them by USB MIDI
|
||||
|
||||
You must select MIDI from the "Tools > USB Type" menu
|
||||
|
||||
This example code is in the public domain.
|
||||
*/
|
||||
|
||||
#include <USBHost_t36.h>
|
||||
|
||||
USBHost myusb;
|
||||
USBHub hub1(myusb);
|
||||
USBHub hub2(myusb);
|
||||
MIDIDevice midi1(myusb);
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// 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("USB Host InputFunctions example");
|
||||
delay(10);
|
||||
myusb.begin();
|
||||
|
||||
midi1.setHandleNoteOn(myNoteOn);
|
||||
midi1.setHandleNoteOff(myNoteOff);
|
||||
midi1.setHandleAfterTouchPoly(myAfterTouchPoly);
|
||||
midi1.setHandleControlChange(myControlChange);
|
||||
midi1.setHandleProgramChange(myProgramChange);
|
||||
midi1.setHandleAfterTouchChannel(myAfterTouchChannel);
|
||||
midi1.setHandlePitchChange(myPitchChange);
|
||||
// Only one of these System Exclusive handlers will actually be
|
||||
// used. See the comments below for the difference between them.
|
||||
midi1.setHandleSystemExclusive(mySystemExclusiveChunk);
|
||||
midi1.setHandleSystemExclusive(mySystemExclusive);
|
||||
midi1.setHandleTimeCodeQuarterFrame(myTimeCodeQuarterFrame);
|
||||
midi1.setHandleSongPosition(mySongPosition);
|
||||
midi1.setHandleSongSelect(mySongSelect);
|
||||
midi1.setHandleTuneRequest(myTuneRequest);
|
||||
midi1.setHandleClock(myClock);
|
||||
midi1.setHandleStart(myStart);
|
||||
midi1.setHandleContinue(myContinue);
|
||||
midi1.setHandleStop(myStop);
|
||||
midi1.setHandleActiveSensing(myActiveSensing);
|
||||
midi1.setHandleSystemReset(mySystemReset);
|
||||
// This generic System Real Time handler is only used if the
|
||||
// more specific ones are not set.
|
||||
midi1.setHandleRealTimeSystem(myRealTimeSystem);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// The handler functions are called when midi1 reads data. They
|
||||
// will not be called automatically. You must call midi1.read()
|
||||
// regularly from loop() for midi1 to actually read incoming
|
||||
// data and run the handler functions as messages arrive.
|
||||
myusb.Task();
|
||||
midi1.read();
|
||||
}
|
||||
|
||||
|
||||
void myNoteOn(byte channel, byte note, byte velocity) {
|
||||
// When a USB device with multiple virtual cables is used,
|
||||
// midi1.getCable() can be used to read which of the virtual
|
||||
// MIDI cables received this message.
|
||||
Serial.print("Note On, ch=");
|
||||
Serial.print(channel, DEC);
|
||||
Serial.print(", note=");
|
||||
Serial.print(note, DEC);
|
||||
Serial.print(", velocity=");
|
||||
Serial.println(velocity, DEC);
|
||||
}
|
||||
|
||||
void myNoteOff(byte channel, byte note, byte velocity) {
|
||||
Serial.print("Note Off, ch=");
|
||||
Serial.print(channel, DEC);
|
||||
Serial.print(", note=");
|
||||
Serial.print(note, DEC);
|
||||
Serial.print(", velocity=");
|
||||
Serial.println(velocity, DEC);
|
||||
}
|
||||
|
||||
void myAfterTouchPoly(byte channel, byte note, byte velocity) {
|
||||
Serial.print("AfterTouch Change, ch=");
|
||||
Serial.print(channel, DEC);
|
||||
Serial.print(", note=");
|
||||
Serial.print(note, DEC);
|
||||
Serial.print(", velocity=");
|
||||
Serial.println(velocity, DEC);
|
||||
}
|
||||
|
||||
void myControlChange(byte channel, byte control, byte value) {
|
||||
Serial.print("Control Change, ch=");
|
||||
Serial.print(channel, DEC);
|
||||
Serial.print(", control=");
|
||||
Serial.print(control, DEC);
|
||||
Serial.print(", value=");
|
||||
Serial.println(value, DEC);
|
||||
}
|
||||
|
||||
void myProgramChange(byte channel, byte program) {
|
||||
Serial.print("Program Change, ch=");
|
||||
Serial.print(channel, DEC);
|
||||
Serial.print(", program=");
|
||||
Serial.println(program, DEC);
|
||||
}
|
||||
|
||||
void myAfterTouchChannel(byte channel, byte pressure) {
|
||||
Serial.print("After Touch, ch=");
|
||||
Serial.print(channel, DEC);
|
||||
Serial.print(", pressure=");
|
||||
Serial.println(pressure, DEC);
|
||||
}
|
||||
|
||||
void myPitchChange(byte channel, int pitch) {
|
||||
Serial.print("Pitch Change, ch=");
|
||||
Serial.print(channel, DEC);
|
||||
Serial.print(", pitch=");
|
||||
Serial.println(pitch, DEC);
|
||||
}
|
||||
|
||||
|
||||
// This 3-input System Exclusive function is more complex, but allows you to
|
||||
// process very large messages which do not fully fit within the midi1's
|
||||
// internal buffer. Large messages are given to you in chunks, with the
|
||||
// 3rd parameter to tell you which is the last chunk. This function is
|
||||
// a Teensy extension, not available in the Arduino MIDI library.
|
||||
//
|
||||
void mySystemExclusiveChunk(const byte *data, uint16_t length, bool last) {
|
||||
Serial.print("SysEx Message: ");
|
||||
printBytes(data, length);
|
||||
if (last) {
|
||||
Serial.println(" (end)");
|
||||
} else {
|
||||
Serial.println(" (to be continued)");
|
||||
}
|
||||
}
|
||||
|
||||
// This simpler 2-input System Exclusive function can only receive messages
|
||||
// up to the size of the internal buffer. Larger messages are truncated, with
|
||||
// no way to receive the data which did not fit in the buffer. If both types
|
||||
// of SysEx functions are set, the 3-input version will be called by midi1.
|
||||
//
|
||||
void mySystemExclusive(byte *data, unsigned int length) {
|
||||
Serial.print("SysEx Message: ");
|
||||
printBytes(data, length);
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void myTimeCodeQuarterFrame(byte data) {
|
||||
static char SMPTE[8]={'0','0','0','0','0','0','0','0'};
|
||||
static byte fps=0;
|
||||
byte index = data >> 4;
|
||||
byte number = data & 15;
|
||||
if (index == 7) {
|
||||
fps = (number >> 1) & 3;
|
||||
number = number & 1;
|
||||
}
|
||||
if (index < 8 || number < 10) {
|
||||
SMPTE[index] = number + '0';
|
||||
Serial.print("TimeCode: "); // perhaps only print when index == 7
|
||||
Serial.print(SMPTE[7]);
|
||||
Serial.print(SMPTE[6]);
|
||||
Serial.print(':');
|
||||
Serial.print(SMPTE[5]);
|
||||
Serial.print(SMPTE[4]);
|
||||
Serial.print(':');
|
||||
Serial.print(SMPTE[3]);
|
||||
Serial.print(SMPTE[2]);
|
||||
Serial.print('.');
|
||||
Serial.print(SMPTE[1]); // perhaps add 2 to compensate for MIDI latency?
|
||||
Serial.print(SMPTE[0]);
|
||||
switch (fps) {
|
||||
case 0: Serial.println(" 24 fps"); break;
|
||||
case 1: Serial.println(" 25 fps"); break;
|
||||
case 2: Serial.println(" 29.97 fps"); break;
|
||||
case 3: Serial.println(" 30 fps"); break;
|
||||
}
|
||||
} else {
|
||||
Serial.print("TimeCode: invalid data = ");
|
||||
Serial.println(data, HEX);
|
||||
}
|
||||
}
|
||||
|
||||
void mySongPosition(uint16_t beats) {
|
||||
Serial.print("Song Position, beat=");
|
||||
Serial.println(beats);
|
||||
}
|
||||
|
||||
void mySongSelect(byte songNumber) {
|
||||
Serial.print("Song Select, song=");
|
||||
Serial.println(songNumber, DEC);
|
||||
}
|
||||
|
||||
void myTuneRequest() {
|
||||
Serial.println("Tune Request");
|
||||
}
|
||||
|
||||
void myClock() {
|
||||
Serial.println("Clock");
|
||||
}
|
||||
|
||||
void myStart() {
|
||||
Serial.println("Start");
|
||||
}
|
||||
|
||||
void myContinue() {
|
||||
Serial.println("Continue");
|
||||
}
|
||||
|
||||
void myStop() {
|
||||
Serial.println("Stop");
|
||||
}
|
||||
|
||||
void myActiveSensing() {
|
||||
Serial.println("Actvice Sensing");
|
||||
}
|
||||
|
||||
void mySystemReset() {
|
||||
Serial.println("System Reset");
|
||||
}
|
||||
|
||||
void myRealTimeSystem(uint8_t realtimebyte) {
|
||||
Serial.print("Real Time Message, code=");
|
||||
Serial.println(realtimebyte, HEX);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void printBytes(const byte *data, unsigned int size) {
|
||||
while (size > 0) {
|
||||
byte b = *data++;
|
||||
if (b < 16) Serial.print('0');
|
||||
Serial.print(b, HEX);
|
||||
if (size > 1) Serial.print(' ');
|
||||
size = size - 1;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user