2016-03-21 15:35:40 +01:00
|
|
|
/*
|
|
|
|
*******************************************************************************
|
|
|
|
* Legacy Serial MIDI and USB Host bidirectional converter
|
|
|
|
* Copyright (C) 2013-2016 Yuuichi Akagawa
|
|
|
|
*
|
|
|
|
* for use with Arduino MIDI library
|
|
|
|
* https://github.com/FortySevenEffects/arduino_midi_library/
|
|
|
|
*
|
|
|
|
* Note:
|
|
|
|
* - If you want use with Leonardo, you must choose Arduino MIDI library v4.0 or higher.
|
|
|
|
* - This is sample program. Do not expect perfect behavior.
|
|
|
|
*******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <MIDI.h>
|
|
|
|
#include <usbh_midi.h>
|
|
|
|
#include <usbhub.h>
|
|
|
|
|
|
|
|
// Satisfy the IDE, which needs to see the include statment in the ino too.
|
|
|
|
#ifdef dobogusinclude
|
|
|
|
#include <spi4teensy3.h>
|
|
|
|
#include <SPI.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//Arduino MIDI library v4.2 compatibility
|
|
|
|
#ifdef MIDI_CREATE_DEFAULT_INSTANCE
|
|
|
|
MIDI_CREATE_DEFAULT_INSTANCE();
|
|
|
|
#endif
|
|
|
|
#ifdef USBCON
|
|
|
|
#define _MIDI_SERIAL_PORT Serial1
|
|
|
|
#else
|
|
|
|
#define _MIDI_SERIAL_PORT Serial
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//////////////////////////
|
|
|
|
// MIDI Pin assign
|
|
|
|
// 2 : GND
|
|
|
|
// 4 : +5V(Vcc) with 220ohm
|
|
|
|
// 5 : TX
|
|
|
|
//////////////////////////
|
|
|
|
|
|
|
|
USB Usb;
|
2016-04-26 16:44:07 +02:00
|
|
|
USBH_MIDI Midi(&Usb);
|
2016-03-21 15:35:40 +01:00
|
|
|
|
|
|
|
void MIDI_poll();
|
|
|
|
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime);
|
|
|
|
|
2016-04-26 16:44:07 +02:00
|
|
|
//If you want handle System Exclusive message, enable this #define otherwise comment out it.
|
|
|
|
#define USBH_MIDI_SYSEX_ENABLE
|
|
|
|
|
|
|
|
#ifdef USBH_MIDI_SYSEX_ENABLE
|
|
|
|
MidiSysEx sysExData;
|
|
|
|
//SysEx:
|
2016-04-26 17:52:39 +02:00
|
|
|
void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {
|
2016-04-26 16:44:07 +02:00
|
|
|
Midi.SendSysEx(sysexmsg, sizeofsysex);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-03-21 15:35:40 +01:00
|
|
|
void setup()
|
|
|
|
{
|
|
|
|
MIDI.begin(MIDI_CHANNEL_OMNI);
|
2016-04-26 16:44:07 +02:00
|
|
|
#ifdef USBH_MIDI_SYSEX_ENABLE
|
|
|
|
MIDI.setHandleSystemExclusive(handle_sysex);
|
|
|
|
#endif
|
2016-03-21 15:35:40 +01:00
|
|
|
if (Usb.Init() == -1) {
|
2016-04-18 18:04:08 +02:00
|
|
|
while (1); //halt
|
2016-03-21 15:35:40 +01:00
|
|
|
}//if (Usb.Init() == -1...
|
|
|
|
delay( 200 );
|
|
|
|
}
|
|
|
|
|
|
|
|
void loop()
|
|
|
|
{
|
|
|
|
unsigned long t1;
|
|
|
|
uint8_t msg[4];
|
|
|
|
|
|
|
|
Usb.Task();
|
|
|
|
t1 = micros();
|
2016-04-18 18:04:08 +02:00
|
|
|
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
|
2016-03-21 15:35:40 +01:00
|
|
|
{
|
|
|
|
MIDI_poll();
|
|
|
|
if (MIDI.read()) {
|
2016-04-18 18:04:08 +02:00
|
|
|
msg[0] = MIDI.getType();
|
2016-04-26 16:44:07 +02:00
|
|
|
switch (msg[0]) {
|
|
|
|
case midi::ActiveSensing :
|
|
|
|
break;
|
|
|
|
case midi::SystemExclusive :
|
|
|
|
//SysEx is handled by event.
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
msg[1] = MIDI.getData1();
|
|
|
|
msg[2] = MIDI.getData2();
|
|
|
|
Midi.SendData(msg, 0);
|
|
|
|
break;
|
2016-04-18 18:04:08 +02:00
|
|
|
}
|
2016-03-21 15:35:40 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//delay(1ms)
|
|
|
|
doDelay(t1, micros(), 1000);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Poll USB MIDI Controler and send to serial MIDI
|
|
|
|
void MIDI_poll()
|
|
|
|
{
|
2016-04-18 18:04:08 +02:00
|
|
|
uint8_t size;
|
2016-04-26 16:44:07 +02:00
|
|
|
#ifdef USBH_MIDI_SYSEX_ENABLE
|
|
|
|
uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
|
|
|
|
uint8_t rcode = 0; //return code
|
|
|
|
uint16_t rcvd;
|
|
|
|
uint8_t readPtr = 0;
|
|
|
|
|
|
|
|
rcode = Midi.RecvData( &rcvd, recvBuf);
|
2016-03-21 15:35:40 +01:00
|
|
|
|
2016-04-26 16:44:07 +02:00
|
|
|
//data check
|
|
|
|
if (rcode != 0) return;
|
|
|
|
if ( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
|
|
|
|
return ;
|
2016-04-18 18:04:08 +02:00
|
|
|
}
|
2016-04-26 16:44:07 +02:00
|
|
|
|
|
|
|
uint8_t *p = recvBuf;
|
|
|
|
while (readPtr < MIDI_EVENT_PACKET_SIZE) {
|
|
|
|
if (*p == 0 && *(p + 1) == 0) break; //data end
|
|
|
|
MidiSysEx::Status rc = sysExData.set(p);
|
|
|
|
switch (rc) {
|
|
|
|
case MidiSysEx::nonsysex : //No SysEx message send data to Serial MIDI
|
|
|
|
p++;
|
|
|
|
size = Midi.lookupMsgSize(*p);
|
|
|
|
_MIDI_SERIAL_PORT.write(p, size);
|
|
|
|
p += 3;
|
|
|
|
break;
|
|
|
|
case MidiSysEx::done : //SysEx end. send data to Serial MIDI
|
|
|
|
_MIDI_SERIAL_PORT.write(sysExData.get(), sysExData.getSize());
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
case MidiSysEx::overflow : //SysEx buffer over. ignore and flush buffer.
|
|
|
|
sysExData.clear();
|
|
|
|
/* FALLTHROUGH */
|
|
|
|
default:
|
|
|
|
p += 4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
readPtr += 4;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
uint8_t outBuf[ 3 ];
|
|
|
|
do {
|
|
|
|
if ( (size = Midi.RecvData(outBuf)) > 0 ) {
|
|
|
|
//MIDI Output
|
|
|
|
_MIDI_SERIAL_PORT.write(outBuf, size);
|
|
|
|
}
|
|
|
|
} while (size > 0);
|
|
|
|
#endif
|
2016-03-21 15:35:40 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Delay time (max 16383 us)
|
|
|
|
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime)
|
|
|
|
{
|
2016-04-18 18:04:08 +02:00
|
|
|
unsigned long t3;
|
2016-03-21 15:35:40 +01:00
|
|
|
|
2016-04-18 18:04:08 +02:00
|
|
|
if ( t1 > t2 ) {
|
2016-04-24 02:02:33 +02:00
|
|
|
t3 = (0xFFFFFFFF - t1 + t2);
|
2016-04-18 18:04:08 +02:00
|
|
|
} else {
|
|
|
|
t3 = t2 - t1;
|
|
|
|
}
|
2016-03-21 15:35:40 +01:00
|
|
|
|
2016-04-18 18:04:08 +02:00
|
|
|
if ( t3 < delayTime ) {
|
|
|
|
delayMicroseconds(delayTime - t3);
|
|
|
|
}
|
2016-03-21 15:35:40 +01:00
|
|
|
}
|