Update MIDI driver v0.3.2

This commit is contained in:
Yuuichi Akagawa 2017-02-26 23:01:08 +09:00
parent 07de430af0
commit 43f423e15d
7 changed files with 121 additions and 154 deletions

View file

@ -51,7 +51,7 @@ env:
- PLATFORMIO_CI_SRC=examples/PSBuzz
# - PLATFORMIO_CI_SRC=examples/testusbhostFAT
- PLATFORMIO_CI_SRC=examples/USB_desc
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/bidrectional_converter
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/bidirectional_converter
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/eVY1_sample
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter
- PLATFORMIO_CI_SRC=examples/USBH_MIDI/USB_MIDI_converter_multi

View file

@ -1,7 +1,7 @@
/*
*******************************************************************************
* USB-MIDI dump utility
* Copyright (C) 2013-2016 Yuuichi Akagawa
* Copyright (C) 2013-2017 Yuuichi Akagawa
*
* for use with USB Host Shield 2.0 from Circuitsathome.com
* https://github.com/felis/USB_Host_Shield_2.0
@ -24,7 +24,7 @@ USB Usb;
USBH_MIDI Midi(&Usb);
void MIDI_poll();
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime);
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
boolean bFirst;
uint16_t pid, vid;
@ -46,13 +46,13 @@ void loop()
//unsigned long t1;
Usb.Task();
//t1 = micros();
//uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
MIDI_poll();
}
//delay(1ms)
//doDelay(t1, micros(), 1000);
//doDelay(t1, (uint32_t)micros(), 1000);
}
// Poll USB MIDI Controler and send to serial MIDI
@ -69,11 +69,7 @@ void MIDI_poll()
pid = Midi.pid;
}
if (Midi.RecvData( &rcvd, bufMidi) == 0 ) {
#ifdef __ARDUINO_ARC__
sprintf(buf, "%016llX: ", millis()); // millis() is 64-bits on the Arduino/Genuino 101
#else
sprintf(buf, "%08lX: ", millis());
#endif
sprintf(buf, "%08lX: ", (uint32_t)millis());
Serial.print(buf);
Serial.print(rcvd);
Serial.print(':');
@ -86,9 +82,9 @@ void MIDI_poll()
}
// Delay time (max 16383 us)
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
unsigned long t3;
uint32_t t3;
if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2);

View file

@ -1,7 +1,7 @@
/*
*******************************************************************************
* USB-MIDI to Legacy Serial MIDI converter
* Copyright (C) 2012-2016 Yuuichi Akagawa
* Copyright (C) 2012-2017 Yuuichi Akagawa
*
* Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com
@ -35,7 +35,7 @@ USB Usb;
USBH_MIDI Midi(&Usb);
void MIDI_poll();
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime);
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
void setup()
{
@ -49,16 +49,14 @@ void setup()
void loop()
{
unsigned long t1;
Usb.Task();
t1 = micros();
uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
MIDI_poll();
}
//delay(1ms)
doDelay(t1, micros(), 1000);
doDelay(t1, (uint32_t)micros(), 1000);
}
// Poll USB MIDI Controler and send to serial MIDI
@ -76,9 +74,9 @@ void MIDI_poll()
}
// Delay time (max 16383 us)
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
unsigned long t3;
uint32_t t3;
if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2);

View file

@ -1,7 +1,7 @@
/*
*******************************************************************************
* USB-MIDI to Legacy Serial MIDI converter
* Copyright (C) 2012-2016 Yuuichi Akagawa
* Copyright (C) 2012-2017 Yuuichi Akagawa
*
* Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com
@ -37,7 +37,7 @@ USBH_MIDI Midi1(&Usb);
USBH_MIDI Midi2(&Usb);
void MIDI_poll();
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime);
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime);
void setup()
{
@ -51,16 +51,14 @@ void setup()
void loop()
{
unsigned long t1;
Usb.Task();
t1 = micros();
uint32_t t1 = (uint32_t)micros();
if ( Usb.getUsbTaskState() == USB_STATE_RUNNING )
{
MIDI_poll();
}
//delay(1ms)
doDelay(t1, micros(), 1000);
doDelay(t1, (uint32_t)micros(), 1000);
}
// Poll USB MIDI Controler and send to serial MIDI
@ -84,9 +82,9 @@ void MIDI_poll()
}
// Delay time (max 16383 us)
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
unsigned long t3;
uint32_t t3;
if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2);

View file

@ -1,7 +1,7 @@
/*
*******************************************************************************
* Legacy Serial MIDI and USB Host bidirectional converter
* Copyright (C) 2013-2016 Yuuichi Akagawa
* Copyright (C) 2013-2017 Yuuichi Akagawa
*
* for use with Arduino MIDI library
* https://github.com/FortySevenEffects/arduino_midi_library/
@ -43,13 +43,12 @@ USB Usb;
USBH_MIDI Midi(&Usb);
void MIDI_poll();
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime);
void doDelay(uint32_t t1, uint32_t t2, uint32_t 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);
@ -70,7 +69,7 @@ void setup()
void loop()
{
unsigned long t1;
uint32_t t1;
uint8_t msg[4];
Usb.Task();
@ -95,7 +94,7 @@ void loop()
}
}
//delay(1ms)
doDelay(t1, micros(), 1000);
doDelay(t1, (uint32_t)micros(), 1000);
}
// Poll USB MIDI Controler and send to serial MIDI
@ -119,28 +118,22 @@ void MIDI_poll()
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;
uint8_t outbuf[3];
uint8_t rc = Midi.extractSysExData(p, outbuf);
if ( rc == 0 ) {
p++;
size = Midi.lookupMsgSize(*p);
_MIDI_SERIAL_PORT.write(p, size);
p += 3;
} else {
_MIDI_SERIAL_PORT.write(outbuf, rc);
p += 4;
}
readPtr += 4;
}
#else
uint8_t outBuf[ 3 ];
uint8_t outBuf[3];
do {
if ( (size = Midi.RecvData(outBuf)) > 0 ) {
//MIDI Output
@ -151,9 +144,9 @@ void MIDI_poll()
}
// Delay time (max 16383 us)
void doDelay(unsigned long t1, unsigned long t2, unsigned long delayTime)
void doDelay(uint32_t t1, uint32_t t2, uint32_t delayTime)
{
unsigned long t3;
uint32_t t3;
if ( t1 > t2 ) {
t3 = (0xFFFFFFFF - t1 + t2);

View file

@ -1,7 +1,7 @@
/*
*******************************************************************************
* USB-MIDI class driver for USB Host Shield 2.0 Library
* Copyright (c) 2012-2016 Yuuichi Akagawa
* Copyright (c) 2012-2017 Yuuichi Akagawa
*
* Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com
@ -93,11 +93,9 @@ isMidiFound(false),
readPtr(0) {
// initialize endpoint data structures
for(uint8_t i=0; i<MIDI_MAX_ENDPOINTS; i++) {
epInfo[i].epAddr = 0;
epInfo[i].epAddr = 0;
epInfo[i].maxPktSize = (i) ? 0 : 8;
epInfo[i].epAttribs = 0;
// epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : 4;
epInfo[i].bmNakPower = (i) ? USB_NAK_NOWAIT : USB_NAK_MAX_POWER;
}
// register in USB subsystem
@ -109,7 +107,7 @@ readPtr(0) {
/* Connection initialization of an MIDI Device */
uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
{
uint8_t buf[DESC_BUFF_SIZE];
uint8_t buf[sizeof (USB_DEVICE_DESCRIPTOR)];
USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
uint8_t rcode;
UsbDevice *p = NULL;
@ -117,6 +115,15 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
uint8_t num_of_conf; // number of configurations
USBTRACE("\rMIDI Init\r\n");
//for reconnect
for(uint8_t i=epDataInIndex; i<=epDataOutIndex; i++) {
epInfo[i].epAddr = (i==epDataInIndex) ? 0x81 : 0x01;
epInfo[i].maxPktSize = 0;
epInfo[i].bmSndToggle = 0;
epInfo[i].bmRcvToggle = 0;
}
// get memory address of USB device address pool
AddressPool &addrPool = pUsb->GetAddressPool();
@ -192,15 +199,18 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
USBTRACE(" PID:"), D_PrintHex(pid, 0x80);
USBTRACE2(" #Conf:", num_of_conf);
isMidiFound = false;
for (uint8_t i=0; i<num_of_conf; i++) {
parseConfigDescr(bAddress, i);
rcode = parseConfigDescr(bAddress, i);
if( rcode )
goto FailGetConfDescr;
if (bNumEP > 1)
break;
} // for
USBTRACE2("\r\nNumEP:", bNumEP);
if( bNumEP < 3 ){ //Device not found.
if( bNumEP < 2 ){ //Device not found.
rcode = 0xff;
goto FailGetConfDescr;
}
@ -214,7 +224,7 @@ uint8_t USBH_MIDI::Init(uint8_t parent, uint8_t port, bool lowspeed)
}
// Assign epInfo to epinfo pointer
rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
rcode = pUsb->setEpInfoEntry(bAddress, 3, epInfo);
USBTRACE2("Conf:", bConfNum);
USBTRACE2("EPin :", (uint8_t)(epInfo[epDataInIndex].epAddr + 0x80));
USBTRACE2("EPout:", epInfo[epDataOutIndex].epAddr);
@ -236,7 +246,7 @@ FailSetConfDescr:
}
/* get and parse config descriptor */
void USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
uint8_t USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
{
uint8_t buf[ DESC_BUFF_SIZE ];
uint8_t* buf_ptr = buf;
@ -245,12 +255,12 @@ void USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
uint8_t descr_type;
unsigned int total_length;
USB_ENDPOINT_DESCRIPTOR *epDesc;
boolean isMidi = false;
bool isMidi = false;
// get configuration descriptor (get descriptor size only)
rcode = pUsb->getConfDescr( addr, 0, 4, conf, buf );
if( rcode ){
return;
return rcode;
}
total_length = buf[2] | ((int)buf[3] << 8);
if( total_length > DESC_BUFF_SIZE ) { //check if total length is larger than buffer
@ -260,7 +270,7 @@ void USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
// get configuration descriptor (all)
rcode = pUsb->getConfDescr( addr, 0, total_length, conf, buf ); //get the whole descriptor
if( rcode ){
return;
return rcode;
}
//parsing descriptors
@ -313,6 +323,7 @@ void USBH_MIDI::parseConfigDescr( uint8_t addr, uint8_t conf )
}//switch( descr_type
buf_ptr += descr_length; //advance buffer pointer
}//while( buf_ptr <=...
return 0;
}
/* Performs a cleanup after failed Init() attempt */
@ -340,12 +351,12 @@ uint8_t USBH_MIDI::RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
}
/* Receive data from MIDI device */
uint8_t USBH_MIDI::RecvData(uint8_t *outBuf)
uint8_t USBH_MIDI::RecvData(uint8_t *outBuf, bool isRaw)
{
uint8_t rcode = 0; //return code
uint16_t rcvd;
if( bPollEnable == false ) return false;
if( bPollEnable == false ) return 0;
//Checking unprocessed message in buffer.
if( readPtr != 0 && readPtr < MIDI_EVENT_PACKET_SIZE ){
@ -368,14 +379,22 @@ uint8_t USBH_MIDI::RecvData(uint8_t *outBuf)
}
RecvData_return_from_buffer:
uint8_t m;
uint8_t cin = recvBuf[readPtr];
if( isRaw == true ) {
*(outBuf++) = cin;
}
readPtr++;
outBuf[0] = recvBuf[readPtr];
readPtr++;
outBuf[1] = recvBuf[readPtr];
readPtr++;
outBuf[2] = recvBuf[readPtr];
readPtr++;
return lookupMsgSize(outBuf[0]);
*(outBuf++) = m = recvBuf[readPtr++];
*(outBuf++) = recvBuf[readPtr++];
*(outBuf++) = recvBuf[readPtr++];
return lookupMsgSize(m, cin);
}
/* Receive raw data from MIDI device */
uint8_t USBH_MIDI::RecvRawData(uint8_t *outBuf)
{
return RecvData(outBuf, true);
}
/* Send data to MIDI device */
@ -443,10 +462,18 @@ void USBH_MIDI::PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr )
/*Return */
/* 0 : undefined message */
/* 0<: Vaild message size(1-3) */
uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg)
uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg, uint8_t cin)
{
uint8_t msgSize = 0;
//SysEx message?
cin = cin & 0x0f;
if( (cin & 0xc) == 4 ) {
if( cin == 4 || cin == 7 ) return 3;
if( cin == 6 ) return 2;
if( cin == 5 ) return 1;
}
if( midiMsg < 0xf0 ) midiMsg &= 0xf0;
switch(midiMsg) {
//3 bytes messages
@ -486,7 +513,7 @@ uint8_t USBH_MIDI::lookupMsgSize(uint8_t midiMsg)
}
/* SysEx data size counter */
unsigned int USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
uint16_t USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
{
unsigned int c = 1;
@ -500,8 +527,8 @@ unsigned int USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
dataptr++;
c++;
//Limiter (upto 256 bytes)
if(c > 256){
//Limiter (default: 256 bytes)
if(c > MIDI_MAX_SYSEX_SIZE){
c = 0;
break;
}
@ -510,15 +537,17 @@ unsigned int USBH_MIDI::countSysExDataSize(uint8_t *dataptr)
}
/* Send SysEx message to MIDI device */
uint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, unsigned int datasize, uint8_t nCable)
uint8_t USBH_MIDI::SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable)
{
uint8_t buf[64];
uint8_t rc;
unsigned int n = datasize;
unsigned int pktSize = (n*10/3+7)/10*4; //Calculate total USB MIDI packet size
uint8_t buf[MIDI_EVENT_PACKET_SIZE];
uint8_t rc = 0;
uint16_t n = datasize;
uint16_t pktSize = (n*10/3+7)/10*4; //Calculate total USB MIDI packet size
uint8_t wptr = 0;
uint8_t maxpkt = epInfo[epDataInIndex].maxPktSize;
if( maxpkt > MIDI_EVENT_PACKET_SIZE ) maxpkt = MIDI_EVENT_PACKET_SIZE;
USBTRACE("SendSysEx:\r\t");
USBTRACE2(" Length:\t", datasize);
USBTRACE2(" Total pktSize:\t", pktSize);
@ -571,60 +600,33 @@ uint8_t USBH_MIDI::SendRawData(uint16_t bytes_send, uint8_t *dataptr)
}
//
// System Exclusive packet data management class
//
MidiSysEx::MidiSysEx()
uint8_t USBH_MIDI::extractSysExData(uint8_t *p, uint8_t *buf)
{
clear();
}
void MidiSysEx::clear()
{
pos = 0;
buf[0] = 0;
}
MidiSysEx::Status MidiSysEx::set(uint8_t *p)
{
MidiSysEx::Status rc = MidiSysEx::ok;
uint8_t rc = 0;
uint8_t cin = *(p) & 0x0f;
//SysEx message?
if( (cin & 0xc) != 4 ) return MidiSysEx::nonsysex;
if( (cin & 0xc) != 4 ) return rc;
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;
}
*buf++ = *(p+1);
*buf++ = *(p+2);
*buf++ = *(p+3);
rc = 3;
break;
case 6:
if( pos < MIDI_EVENT_PACKET_SIZE ) {
buf[pos++] = *(p+1);
}else{
rc = MidiSysEx::overflow;
}
*buf++ = *(p+1);
*buf++ = *(p+2);
rc = 2;
break;
case 5:
*buf++ = *(p+1);
rc = 1;
break;
default:
break;
}
//SysEx end?
if((cin & 0x3) != 0) {
rc = MidiSysEx::done;
}
return(rc);
}

View file

@ -1,7 +1,7 @@
/*
*******************************************************************************
* USB-MIDI class driver for USB Host Shield 2.0 Library
* Copyright (c) 2012-2016 Yuuichi Akagawa
* Copyright (c) 2012-2017 Yuuichi Akagawa
*
* Idea from LPK25 USB-MIDI to Serial MIDI converter
* by Collin Cunningham - makezine.com, narbotic.com
@ -33,6 +33,7 @@
#define USB_SUBCLASS_MIDISTREAMING 3
#define DESC_BUFF_SIZE 256
#define MIDI_EVENT_PACKET_SIZE 64
#define MIDI_MAX_SYSEX_SIZE 256
class USBH_MIDI;
class USBH_MIDI : public USBDeviceConfig
@ -57,8 +58,8 @@ protected:
uint8_t recvBuf[MIDI_EVENT_PACKET_SIZE];
uint8_t readPtr;
void parseConfigDescr(uint8_t addr, uint8_t conf);
unsigned int countSysExDataSize(uint8_t *dataptr);
uint8_t parseConfigDescr(uint8_t addr, uint8_t conf);
uint16_t countSysExDataSize(uint8_t *dataptr);
#ifdef DEBUG_USB_HOST
void PrintEndpointDescriptor( const USB_ENDPOINT_DESCRIPTOR* ep_ptr );
#endif
@ -67,10 +68,12 @@ public:
USBH_MIDI(USB *p);
// Methods for recieving and sending data
uint8_t RecvData(uint16_t *bytes_rcvd, uint8_t *dataptr);
uint8_t RecvData(uint8_t *outBuf);
uint8_t RecvData(uint8_t *outBuf, bool isRaw=false);
uint8_t RecvRawData(uint8_t *outBuf);
uint8_t SendData(uint8_t *dataptr, uint8_t nCable=0);
uint8_t lookupMsgSize(uint8_t midiMsg);
uint8_t SendSysEx(uint8_t *dataptr, unsigned int datasize, uint8_t nCable=0);
uint8_t lookupMsgSize(uint8_t midiMsg, uint8_t cin=0);
uint8_t SendSysEx(uint8_t *dataptr, uint16_t datasize, uint8_t nCable=0);
uint8_t extractSysExData(uint8_t *p, uint8_t *buf);
uint8_t SendRawData(uint16_t bytes_send, uint8_t *dataptr);
// backward compatibility functions
inline uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr){ return RecvData(bytes_rcvd, dataptr); };
@ -81,27 +84,4 @@ public:
virtual uint8_t Release();
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_