mirror of
https://github.com/felis/USB_Host_Shield_2.0.git
synced 2024-03-22 11:31:26 +01:00
Merge pull request #232 from YuuichiAkagawa/pr_usbh_midi_031
Update MIDI driver v0.3.1
This commit is contained in:
commit
2295571e2d
7 changed files with 252 additions and 93 deletions
|
@ -320,8 +320,8 @@ HID devices are also supported by the library. However these require you to writ
|
||||||
The library support MIDI devices.
|
The library support MIDI devices.
|
||||||
You can convert USB MIDI keyboard to legacy serial MIDI.
|
You can convert USB MIDI keyboard to legacy serial MIDI.
|
||||||
|
|
||||||
* [USB_MIDI_converter.ino](USBH_MIDI/USB_MIDI_converter)
|
* [USB_MIDI_converter.ino](examples/USBH_MIDI/USB_MIDI_converter/USB_MIDI_converter.ino)
|
||||||
* [USB_MIDI_converter_multi.ino](USBH_MIDI/USB_MIDI_converter_multi)
|
* [USB_MIDI_converter_multi.ino](examples/USBH_MIDI/USB_MIDI_converter_multi/USB_MIDI_converter_multi.ino)
|
||||||
|
|
||||||
For information see the following page: <http://yuuichiakagawa.github.io/USBH_MIDI/>.
|
For information see the following page: <http://yuuichiakagawa.github.io/USBH_MIDI/>.
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,7 @@ void loop()
|
||||||
// Poll USB MIDI Controler and send to serial MIDI
|
// Poll USB MIDI Controler and send to serial MIDI
|
||||||
void MIDI_poll()
|
void MIDI_poll()
|
||||||
{
|
{
|
||||||
byte outBuf[ 3 ];
|
uint8_t outBuf[ 3 ];
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -66,7 +66,7 @@ void loop()
|
||||||
// Poll USB MIDI Controler and send to serial MIDI
|
// Poll USB MIDI Controler and send to serial MIDI
|
||||||
void MIDI_poll()
|
void MIDI_poll()
|
||||||
{
|
{
|
||||||
byte outBuf[ 3 ];
|
uint8_t outBuf[ 3 ];
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
|
@ -40,15 +40,28 @@ MIDI_CREATE_DEFAULT_INSTANCE();
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
|
|
||||||
USB Usb;
|
USB Usb;
|
||||||
USBH_MIDI Midi(&Usb);
|
USBH_MIDI Midi(&Usb);
|
||||||
|
|
||||||
void MIDI_poll();
|
void MIDI_poll();
|
||||||
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime);
|
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime);
|
||||||
|
|
||||||
|
//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:
|
||||||
|
void handle_sysex( byte* sysexmsg, unsigned sizeofsysex) {
|
||||||
|
Midi.SendSysEx(sysexmsg, sizeofsysex);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
MIDI.begin(MIDI_CHANNEL_OMNI);
|
MIDI.begin(MIDI_CHANNEL_OMNI);
|
||||||
|
#ifdef USBH_MIDI_SYSEX_ENABLE
|
||||||
|
MIDI.setHandleSystemExclusive(handle_sysex);
|
||||||
|
#endif
|
||||||
if (Usb.Init() == -1) {
|
if (Usb.Init() == -1) {
|
||||||
while (1); //halt
|
while (1); //halt
|
||||||
}//if (Usb.Init() == -1...
|
}//if (Usb.Init() == -1...
|
||||||
|
@ -67,13 +80,17 @@ void loop()
|
||||||
MIDI_poll();
|
MIDI_poll();
|
||||||
if (MIDI.read()) {
|
if (MIDI.read()) {
|
||||||
msg[0] = MIDI.getType();
|
msg[0] = MIDI.getType();
|
||||||
if ( msg[0] == 0xf0 ) { //SysEX
|
switch (msg[0]) {
|
||||||
//TODO
|
case midi::ActiveSensing :
|
||||||
//SysEx implementation is not yet.
|
break;
|
||||||
} else {
|
case midi::SystemExclusive :
|
||||||
msg[1] = MIDI.getData1();
|
//SysEx is handled by event.
|
||||||
msg[2] = MIDI.getData2();
|
break;
|
||||||
Midi.SendData(msg, 0);
|
default :
|
||||||
|
msg[1] = MIDI.getData1();
|
||||||
|
msg[2] = MIDI.getData2();
|
||||||
|
Midi.SendData(msg, 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,13 +101,53 @@ void loop()
|
||||||
// Poll USB MIDI Controler and send to serial MIDI
|
// Poll USB MIDI Controler and send to serial MIDI
|
||||||
void MIDI_poll()
|
void MIDI_poll()
|
||||||
{
|
{
|
||||||
byte outBuf[ 3 ];
|
|
||||||
uint8_t size;
|
uint8_t size;
|
||||||
|
#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;
|
||||||
|
|
||||||
if ( (size = Midi.RecvData(outBuf)) > 0 ) {
|
rcode = Midi.RecvData( &rcvd, recvBuf);
|
||||||
//MIDI Output
|
|
||||||
_MIDI_SERIAL_PORT.write(outBuf, size);
|
//data check
|
||||||
|
if (rcode != 0) return;
|
||||||
|
if ( recvBuf[0] == 0 && recvBuf[1] == 0 && recvBuf[2] == 0 && recvBuf[3] == 0 ) {
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delay time (max 16383 us)
|
// Delay time (max 16383 us)
|
||||||
|
|
|
@ -61,7 +61,7 @@ void loop()
|
||||||
// Poll USB MIDI Controler
|
// Poll USB MIDI Controler
|
||||||
void MIDI_poll()
|
void MIDI_poll()
|
||||||
{
|
{
|
||||||
byte inBuf[ 3 ];
|
uint8_t inBuf[ 3 ];
|
||||||
|
|
||||||
//first call?
|
//first call?
|
||||||
if (Midi.vid != vid || Midi.pid != pid) {
|
if (Midi.vid != vid || Midi.pid != pid) {
|
||||||
|
|
218
usbh_midi.cpp
Executable file → Normal file
218
usbh_midi.cpp
Executable file → Normal file
|
@ -116,11 +116,10 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
EpInfo *oldep_ptr = NULL;
|
EpInfo *oldep_ptr = NULL;
|
||||||
uint8_t num_of_conf; // number of configurations
|
uint8_t num_of_conf; // number of configurations
|
||||||
|
|
||||||
|
USBTRACE("\rMIDI Init\r\n");
|
||||||
// get memory address of USB device address pool
|
// get memory address of USB device address pool
|
||||||
AddressPool &addrPool = pUsb->GetAddressPool();
|
AddressPool &addrPool = pUsb->GetAddressPool();
|
||||||
#ifdef DEBUG_USB_HOST
|
|
||||||
USBTRACE("\rMIDI Init\r\n");
|
|
||||||
#endif
|
|
||||||
// check if address has already been assigned to an instance
|
// check if address has already been assigned to an instance
|
||||||
if (bAddress) {
|
if (bAddress) {
|
||||||
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
return USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE;
|
||||||
|
@ -169,9 +168,8 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
bAddress = 0;
|
bAddress = 0;
|
||||||
return rcode;
|
return rcode;
|
||||||
}//if (rcode...
|
}//if (rcode...
|
||||||
#ifdef DEBUG_USB_HOST
|
|
||||||
USBTRACE2("Addr:", bAddress);
|
USBTRACE2("Addr:", bAddress);
|
||||||
#endif
|
|
||||||
p->lowspeed = false;
|
p->lowspeed = false;
|
||||||
|
|
||||||
//get pointer to assigned address record
|
//get pointer to assigned address record
|
||||||
|
@ -186,27 +184,29 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
// Assign epInfo to epinfo pointer
|
// Assign epInfo to epinfo pointer
|
||||||
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
|
rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
|
||||||
if (rcode) {
|
if (rcode) {
|
||||||
#ifdef DEBUG_USB_HOST
|
|
||||||
USBTRACE("setEpInfoEntry failed");
|
USBTRACE("setEpInfoEntry failed");
|
||||||
#endif
|
|
||||||
goto FailSetDevTblEntry;
|
goto FailSetDevTblEntry;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_USB_HOST
|
|
||||||
USBTRACE2("NC:", num_of_conf);
|
USBTRACE("VID:"), D_PrintHex(vid, 0x80);
|
||||||
#endif
|
USBTRACE(" PID:"), D_PrintHex(pid, 0x80);
|
||||||
|
USBTRACE2(" #Conf:", num_of_conf);
|
||||||
|
|
||||||
for (uint8_t i=0; i<num_of_conf; i++) {
|
for (uint8_t i=0; i<num_of_conf; i++) {
|
||||||
parseConfigDescr(bAddress, i);
|
parseConfigDescr(bAddress, i);
|
||||||
if (bNumEP > 1)
|
if (bNumEP > 1)
|
||||||
break;
|
break;
|
||||||
} // for
|
} // for
|
||||||
#ifdef DEBUG_USB_HOST
|
|
||||||
USBTRACE2("NumEP:", bNumEP);
|
USBTRACE2("\r\nNumEP:", bNumEP);
|
||||||
#endif
|
|
||||||
if( bConfNum == 0 ){ //Device not found.
|
if( bNumEP < 3 ){ //Device not found.
|
||||||
|
rcode = 0xff;
|
||||||
goto FailGetConfDescr;
|
goto FailGetConfDescr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( !isMidiFound ){ //MIDI Device not found. Try first Bulk transfer device
|
if( !isMidiFound ){ //MIDI Device not found. Try last Bulk transfer device
|
||||||
|
USBTRACE("MIDI not found. Attempts bulk device\r\n");
|
||||||
epInfo[epDataInIndex].epAddr = epInfo[epDataInIndexVSP].epAddr;
|
epInfo[epDataInIndex].epAddr = epInfo[epDataInIndexVSP].epAddr;
|
||||||
epInfo[epDataInIndex].maxPktSize = epInfo[epDataInIndexVSP].maxPktSize;
|
epInfo[epDataInIndex].maxPktSize = epInfo[epDataInIndexVSP].maxPktSize;
|
||||||
epInfo[epDataOutIndex].epAddr = epInfo[epDataOutIndexVSP].epAddr;
|
epInfo[epDataOutIndex].epAddr = epInfo[epDataOutIndexVSP].epAddr;
|
||||||
|
@ -215,18 +215,17 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
|
||||||
|
|
||||||
// Assign epInfo to epinfo pointer
|
// Assign epInfo to epinfo pointer
|
||||||
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
|
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
|
||||||
#ifdef DEBUG_USB_HOST
|
|
||||||
USBTRACE2("Conf:", bConfNum);
|
USBTRACE2("Conf:", bConfNum);
|
||||||
#endif
|
USBTRACE2("EPin :", (uint8_t)(epInfo[epDataInIndex].epAddr + 0x80));
|
||||||
|
USBTRACE2("EPout:", epInfo[epDataOutIndex].epAddr);
|
||||||
|
|
||||||
// Set Configuration Value
|
// Set Configuration Value
|
||||||
rcode = pUsb->setConf(bAddress, 0, bConfNum);
|
rcode = pUsb->setConf(bAddress, 0, bConfNum);
|
||||||
if (rcode) {
|
if (rcode) {
|
||||||
goto FailSetConfDescr;
|
goto FailSetConfDescr;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG_USB_HOST
|
|
||||||
USBTRACE("Init done.");
|
|
||||||
#endif
|
|
||||||
bPollEnable = true;
|
bPollEnable = true;
|
||||||
|
USBTRACE("Init done.\r\n");
|
||||||
return 0;
|
return 0;
|
||||||
FailGetDevDescr:
|
FailGetDevDescr:
|
||||||
FailSetDevTblEntry:
|
FailSetDevTblEntry:
|
||||||
|
@ -237,13 +236,13 @@ FailSetConfDescr:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get and parse config descriptor */
|
/* get and parse config descriptor */
|
||||||
void USBH_MIDI::parseConfigDescr( byte addr, byte conf )
|
void USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
|
||||||
{
|
{
|
||||||
uint8_t buf[ DESC_BUFF_SIZE ];
|
uint8_t buf[ DESC_BUFF_SIZE ];
|
||||||
uint8_t* buf_ptr = buf;
|
uint8_t* buf_ptr = buf;
|
||||||
byte rcode;
|
uint8_t rcode;
|
||||||
byte descr_length;
|
uint8_t descr_length;
|
||||||
byte descr_type;
|
uint8_t descr_type;
|
||||||
unsigned int total_length;
|
unsigned int total_length;
|
||||||
USB_ENDPOINT_DESCRIPTOR *epDesc;
|
USB_ENDPOINT_DESCRIPTOR *epDesc;
|
||||||
boolean isMidi = false;
|
boolean isMidi = false;
|
||||||
|
@ -273,18 +272,28 @@ void USBH_MIDI::parseConfigDescr( byte addr, byte conf )
|
||||||
bConfNum = buf_ptr[5];
|
bConfNum = buf_ptr[5];
|
||||||
break;
|
break;
|
||||||
case USB_DESCRIPTOR_INTERFACE :
|
case USB_DESCRIPTOR_INTERFACE :
|
||||||
|
USBTRACE("\r\nConf:"), D_PrintHex(bConfNum, 0x80);
|
||||||
|
USBTRACE(" Int:"), D_PrintHex(buf_ptr[2], 0x80);
|
||||||
|
USBTRACE(" Alt:"), D_PrintHex(buf_ptr[3], 0x80);
|
||||||
|
USBTRACE(" EPs:"), D_PrintHex(buf_ptr[4], 0x80);
|
||||||
|
USBTRACE(" IntCl:"), D_PrintHex(buf_ptr[5], 0x80);
|
||||||
|
USBTRACE(" IntSubCl:"), D_PrintHex(buf_ptr[6], 0x80);
|
||||||
|
USBTRACE("\r\n");
|
||||||
|
|
||||||
if( buf_ptr[5] == USB_CLASS_AUDIO && buf_ptr[6] == USB_SUBCLASS_MIDISTREAMING ) { //p[5]; bInterfaceClass = 1(Audio), p[6]; bInterfaceSubClass = 3(MIDI Streaming)
|
if( buf_ptr[5] == USB_CLASS_AUDIO && buf_ptr[6] == USB_SUBCLASS_MIDISTREAMING ) { //p[5]; bInterfaceClass = 1(Audio), p[6]; bInterfaceSubClass = 3(MIDI Streaming)
|
||||||
isMidiFound = true; //MIDI device found.
|
isMidiFound = true; //MIDI device found.
|
||||||
isMidi = true;
|
isMidi = true;
|
||||||
|
USBTRACE("MIDI Device\r\n");
|
||||||
}else{
|
}else{
|
||||||
#ifdef DEBUG_USB_HOST
|
|
||||||
USBTRACE("No MIDI Device\n");
|
|
||||||
#endif
|
|
||||||
isMidi = false;
|
isMidi = false;
|
||||||
|
USBTRACE("No MIDI Device\r\n");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case USB_DESCRIPTOR_ENDPOINT :
|
case USB_DESCRIPTOR_ENDPOINT :
|
||||||
epDesc = (USB_ENDPOINT_DESCRIPTOR *)buf_ptr;
|
epDesc = (USB_ENDPOINT_DESCRIPTOR *)buf_ptr;
|
||||||
|
USBTRACE("-EPAddr:"), D_PrintHex(epDesc->bEndpointAddress, 0x80);
|
||||||
|
USBTRACE(" bmAttr:"), D_PrintHex(epDesc->bmAttributes, 0x80);
|
||||||
|
USBTRACE2(" MaxPktSz:", (uint8_t)epDesc->wMaxPacketSize);
|
||||||
if ((epDesc->bmAttributes & 0x02) == 2) {//bulk
|
if ((epDesc->bmAttributes & 0x02) == 2) {//bulk
|
||||||
uint8_t index;
|
uint8_t index;
|
||||||
if( isMidi )
|
if( isMidi )
|
||||||
|
@ -333,7 +342,7 @@ uint8_t USBH_MIDI::RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
|
||||||
/* Receive data from MIDI device */
|
/* Receive data from MIDI device */
|
||||||
uint8_t USBH_MIDI::RecvData(uint8_t *outBuf)
|
uint8_t USBH_MIDI::RecvData(uint8_t *outBuf)
|
||||||
{
|
{
|
||||||
byte rcode = 0; //return code
|
uint8_t rcode = 0; //return code
|
||||||
uint16_t rcvd;
|
uint16_t rcvd;
|
||||||
|
|
||||||
if( bPollEnable == false ) return false;
|
if( bPollEnable == false ) return false;
|
||||||
|
@ -370,10 +379,10 @@ RecvData_return_from_buffer:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send data to MIDI device */
|
/* Send data to MIDI device */
|
||||||
uint8_t USBH_MIDI::SendData(uint8_t *dataptr, byte nCable)
|
uint8_t USBH_MIDI::SendData(uint8_t *dataptr, uint8_t nCable)
|
||||||
{
|
{
|
||||||
byte buf[4];
|
uint8_t buf[4];
|
||||||
byte msg;
|
uint8_t msg;
|
||||||
|
|
||||||
msg = dataptr[0];
|
msg = dataptr[0];
|
||||||
// SysEx long message ?
|
// SysEx long message ?
|
||||||
|
@ -407,7 +416,7 @@ uint8_t USBH_MIDI::SendData(uint8_t *dataptr, byte nCable)
|
||||||
buf[3] = 0;
|
buf[3] = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//1 bytes message
|
//1 byte message
|
||||||
case 1 :
|
case 1 :
|
||||||
default :
|
default :
|
||||||
buf[2] = 0;
|
buf[2] = 0;
|
||||||
|
@ -420,20 +429,13 @@ uint8_t USBH_MIDI::SendData(uint8_t *dataptr, byte nCable)
|
||||||
#ifdef DEBUG_USB_HOST
|
#ifdef DEBUG_USB_HOST
|
||||||
void USBH_MIDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
|
void USBH_MIDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
|
||||||
{
|
{
|
||||||
Notify(PSTR("Endpoint descriptor:"), 0x80);
|
USBTRACE("Endpoint descriptor:\r\n");
|
||||||
Notify(PSTR("\r\nLength:\t\t"), 0x80);
|
USBTRACE2(" Length:\t", ep_ptr->bLength);
|
||||||
PrintHex<uint8_t>(ep_ptr->bLength, 0x80);
|
USBTRACE2(" Type:\t\t", ep_ptr->bDescriptorType);
|
||||||
Notify(PSTR("\r\nType:\t\t"), 0x80);
|
USBTRACE2(" Address:\t", ep_ptr->bEndpointAddress);
|
||||||
PrintHex<uint8_t>(ep_ptr->bDescriptorType, 0x80);
|
USBTRACE2(" Attributes:\t", ep_ptr->bmAttributes);
|
||||||
Notify(PSTR("\r\nAddress:\t"), 0x80);
|
USBTRACE2(" MaxPktSize:\t", ep_ptr->wMaxPacketSize);
|
||||||
PrintHex<uint8_t>(ep_ptr->bEndpointAddress, 0x80);
|
USBTRACE2(" Poll Intrv:\t", ep_ptr->bInterval);
|
||||||
Notify(PSTR("\r\nAttributes:\t"), 0x80);
|
|
||||||
PrintHex<uint8_t>(ep_ptr->bmAttributes, 0x80);
|
|
||||||
Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
|
|
||||||
PrintHex<uint16_t>(ep_ptr->wMaxPacketSize, 0x80);
|
|
||||||
Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
|
|
||||||
PrintHex<uint8_t>(ep_ptr->bInterval, 0x80);
|
|
||||||
Notify(PSTR("\r\n"), 0x80);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -465,7 +467,7 @@ uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg)
|
||||||
msgSize = 2;
|
msgSize = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//1 bytes messages
|
//1 byte messages
|
||||||
case 0xf8 : //system realtime message
|
case 0xf8 : //system realtime message
|
||||||
case 0xf9 : //system realtime message
|
case 0xf9 : //system realtime message
|
||||||
case 0xfa : //system realtime message
|
case 0xfa : //system realtime message
|
||||||
|
@ -508,43 +510,121 @@ unsigned int USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send SysEx message to MIDI device */
|
/* Send SysEx message to MIDI device */
|
||||||
uint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, unsigned int datasize, byte nCable)
|
uint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, unsigned int datasize, uint8_t nCable)
|
||||||
{
|
{
|
||||||
byte buf[4];
|
uint8_t buf[64];
|
||||||
uint8_t rc;
|
uint8_t rc;
|
||||||
unsigned int n = datasize;
|
unsigned int n = datasize;
|
||||||
|
unsigned int pktSize = (n*10/3+7)/10*4; //Calculate total USB MIDI packet size
|
||||||
|
uint8_t wptr = 0;
|
||||||
|
uint8_t maxpkt = epInfo[epDataInIndex].maxPktSize;
|
||||||
|
|
||||||
|
USBTRACE("SendSysEx:\r\t");
|
||||||
|
USBTRACE2(" Length:\t", datasize);
|
||||||
|
USBTRACE2(" Total pktSize:\t", pktSize);
|
||||||
|
|
||||||
while(n > 0) {
|
while(n > 0) {
|
||||||
//Byte 0
|
//Byte 0
|
||||||
buf[0] = (nCable << 4) | 0x4; //x4 SysEx starts or continues
|
buf[wptr] = (nCable << 4) | 0x4; //x4 SysEx starts or continues
|
||||||
|
|
||||||
switch ( n ) {
|
switch ( n ) {
|
||||||
case 1 :
|
case 1 :
|
||||||
buf[0] = (nCable << 4) | 0x5; //x5 SysEx ends with following single byte.
|
buf[wptr++] = (nCable << 4) | 0x5; //x5 SysEx ends with following single byte.
|
||||||
buf[1] = *(dataptr++);
|
buf[wptr++] = *(dataptr++);
|
||||||
buf[2] = 0x00;
|
buf[wptr++] = 0x00;
|
||||||
buf[3] = 0x00;
|
buf[wptr++] = 0x00;
|
||||||
n = n - 1;
|
n = n - 1;
|
||||||
break;
|
break;
|
||||||
case 2 :
|
case 2 :
|
||||||
buf[0] = (nCable << 4) | 0x6; //x6 SysEx ends with following two bytes.
|
buf[wptr++] = (nCable << 4) | 0x6; //x6 SysEx ends with following two bytes.
|
||||||
buf[1] = *(dataptr++);
|
buf[wptr++] = *(dataptr++);
|
||||||
buf[2] = *(dataptr++);
|
buf[wptr++] = *(dataptr++);
|
||||||
buf[3] = 0x00;
|
buf[wptr++] = 0x00;
|
||||||
n = n - 2;
|
n = n - 2;
|
||||||
break;
|
break;
|
||||||
case 3 :
|
case 3 :
|
||||||
buf[0] = (nCable << 4) | 0x7; //x7 SysEx ends with following three bytes.
|
buf[wptr] = (nCable << 4) | 0x7; //x7 SysEx ends with following three bytes.
|
||||||
default :
|
default :
|
||||||
buf[1] = *(dataptr++);
|
wptr++;
|
||||||
buf[2] = *(dataptr++);
|
buf[wptr++] = *(dataptr++);
|
||||||
buf[3] = *(dataptr++);
|
buf[wptr++] = *(dataptr++);
|
||||||
|
buf[wptr++] = *(dataptr++);
|
||||||
n = n - 3;
|
n = n - 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rc = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, 4, buf);
|
|
||||||
if(rc != 0)
|
if( wptr >= maxpkt || n == 0 ){ //Reach a maxPktSize or data end.
|
||||||
break;
|
USBTRACE2(" wptr:\t", wptr);
|
||||||
|
if( (rc = pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, wptr, buf)) != 0 ){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wptr = 0; //rewind data pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send raw data to MIDI device */
|
||||||
|
uint8_t USBH_MIDI::SendRawData(uint16_t bytes_send, uint8_t *dataptr)
|
||||||
|
{
|
||||||
|
return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, bytes_send, dataptr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// System Exclusive packet data management class
|
||||||
|
//
|
||||||
|
MidiSysEx::MidiSysEx()
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MidiSysEx::clear()
|
||||||
|
{
|
||||||
|
pos = 0;
|
||||||
|
buf[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MidiSysEx::Status MidiSysEx::set(uint8_t *p)
|
||||||
|
{
|
||||||
|
MidiSysEx::Status rc = MidiSysEx::ok;
|
||||||
|
uint8_t cin = *(p) & 0x0f;
|
||||||
|
|
||||||
|
//SysEx message?
|
||||||
|
if( (cin & 0xc) != 4 ) return MidiSysEx::nonsysex;
|
||||||
|
|
||||||
|
switch(cin) {
|
||||||
|
case 4:
|
||||||
|
case 7:
|
||||||
|
if( pos+2 < MIDI_EVENT_PACKET_SIZE ) {
|
||||||
|
buf[pos++] = *(p+1);
|
||||||
|
buf[pos++] = *(p+2);
|
||||||
|
buf[pos++] = *(p+3);
|
||||||
|
}else{
|
||||||
|
rc = MidiSysEx::overflow;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
if( pos+1 < MIDI_EVENT_PACKET_SIZE ) {
|
||||||
|
buf[pos++] = *(p+1);
|
||||||
|
buf[pos++] = *(p+2);
|
||||||
|
}else{
|
||||||
|
rc = MidiSysEx::overflow;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
if( pos < MIDI_EVENT_PACKET_SIZE ) {
|
||||||
|
buf[pos++] = *(p+1);
|
||||||
|
}else{
|
||||||
|
rc = MidiSysEx::overflow;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//SysEx end?
|
||||||
|
if((cin & 0x3) != 0) {
|
||||||
|
rc = MidiSysEx::done;
|
||||||
}
|
}
|
||||||
return(rc);
|
return(rc);
|
||||||
}
|
}
|
||||||
|
|
34
usbh_midi.h
Executable file → Normal file
34
usbh_midi.h
Executable file → Normal file
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#if !defined(_USBH_MIDI_H_)
|
#if !defined(_USBH_MIDI_H_)
|
||||||
#define _USBH_MIDI_H_
|
#define _USBH_MIDI_H_
|
||||||
|
//#define DEBUG_USB_HOST
|
||||||
#include "Usb.h"
|
#include "Usb.h"
|
||||||
|
|
||||||
#define MIDI_MAX_ENDPOINTS 5 //endpoint 0, bulk_IN(MIDI), bulk_OUT(MIDI), bulk_IN(VSP), bulk_OUT(VSP)
|
#define MIDI_MAX_ENDPOINTS 5 //endpoint 0, bulk_IN(MIDI), bulk_OUT(MIDI), bulk_IN(VSP), bulk_OUT(VSP)
|
||||||
|
@ -36,9 +37,6 @@ class USBH_MIDI;
|
||||||
|
|
||||||
class USBH_MIDI : public USBDeviceConfig
|
class USBH_MIDI : public USBDeviceConfig
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
uint8_t lookupMsgSize(uint8_t midiMsg);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const uint8_t epDataInIndex; // DataIn endpoint index(MIDI)
|
static const uint8_t epDataInIndex; // DataIn endpoint index(MIDI)
|
||||||
static const uint8_t epDataOutIndex; // DataOUT endpoint index(MIDI)
|
static const uint8_t epDataOutIndex; // DataOUT endpoint index(MIDI)
|
||||||
|
@ -59,7 +57,7 @@ protected:
|
||||||
uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
|
uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
|
||||||
uint8_t readPtr;
|
uint8_t readPtr;
|
||||||
|
|
||||||
void parseConfigDescr(byte addr, byte conf);
|
void parseConfigDescr(uint8_t addr, uint8_t conf);
|
||||||
unsigned int countSysExDataSize(uint8_t *dataptr);
|
unsigned int countSysExDataSize(uint8_t *dataptr);
|
||||||
#ifdef DEBUG_USB_HOST
|
#ifdef DEBUG_USB_HOST
|
||||||
void PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr );
|
void PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr );
|
||||||
|
@ -70,8 +68,10 @@ public:
|
||||||
// Methods for recieving and sending data
|
// Methods for recieving and sending data
|
||||||
uint8_t RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr);
|
uint8_t RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr);
|
||||||
uint8_t RecvData(uint8_t *outBuf);
|
uint8_t RecvData(uint8_t *outBuf);
|
||||||
uint8_t SendData(uint8_t *dataptr, byte nCable=0);
|
uint8_t SendData(uint8_t *dataptr, uint8_t nCable=0);
|
||||||
uint8_t SendSysEx(uint8_t *dataptr, unsigned int datasize, byte nCable=0);
|
uint8_t lookupMsgSize(uint8_t midiMsg);
|
||||||
|
uint8_t SendSysEx(uint8_t *dataptr, unsigned int datasize, uint8_t nCable=0);
|
||||||
|
uint8_t SendRawData(uint16_t bytes_send, uint8_t *dataptr);
|
||||||
// backward compatibility functions
|
// backward compatibility functions
|
||||||
inline uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr){ return RecvData(bytes_rcvd, dataptr); };
|
inline uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr){ return RecvData(bytes_rcvd, dataptr); };
|
||||||
inline uint8_t RcvData(uint8_t *outBuf){ return RecvData(outBuf); };
|
inline uint8_t RcvData(uint8_t *outBuf){ return RecvData(outBuf); };
|
||||||
|
@ -82,4 +82,26 @@ public:
|
||||||
virtual uint8_t GetAddress() { return bAddress; };
|
virtual uint8_t GetAddress() { return bAddress; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// System Exclusive packet data management class
|
||||||
|
//
|
||||||
|
class MidiSysEx {
|
||||||
|
private:
|
||||||
|
uint8_t pos;
|
||||||
|
uint8_t buf[MIDI_EVENT_PACKET_SIZE];
|
||||||
|
public:
|
||||||
|
typedef enum {
|
||||||
|
nonsysex = 0,
|
||||||
|
ok = 1,
|
||||||
|
done = 0xfe,
|
||||||
|
overflow = 0xff
|
||||||
|
} Status;
|
||||||
|
|
||||||
|
MidiSysEx();
|
||||||
|
void clear();
|
||||||
|
MidiSysEx::Status set(uint8_t *p);
|
||||||
|
inline uint8_t *get(){return buf;};
|
||||||
|
inline uint8_t getSize(){return pos;};
|
||||||
|
};
|
||||||
|
|
||||||
#endif //_USBH_MIDI_H_
|
#endif //_USBH_MIDI_H_
|
||||||
|
|
Loading…
Reference in a new issue