|
- /* 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;
- }
- }
|