Hi ,
finally i got my "Yamaha THR10" (guitar amp, that can be configured via MIDI-SysEx) working with this library (arduino-libraries/USBHost) in conjunction with the" bbx10/USBH-Midi branch Due"-library on my "Arduino Due", but there were several problems to solve before:
Concerning this library (arduino-libraries/USBHost):
USB-Enumeration works only, if Debug-outputs are enabled in USBHost.h
#define TRACE_USBHOST(x) x
//#define TRACE_USBHOST(x)
otherwise device is not detected.
Don't ask me why...
Is it perhaps a timing problem, that is solved when a "printf" delays process at the right time?
EDIT:
In fact it is a timing issue, I found out after som research. There a two places to add delays (details at th bottom of this posting).
Just for further information
Issues concerning library (bbx10/USBH-Midi branch Due):
- Adding an "else if" in descriptor parsing
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.
isMidi = true;
}
//**Yamaha THR10**
else if( buf_ptr[5] == USB_CLASS_VENDOR_SPECIFIC && buf_ptr[6] == USB_SUBCLASS_MIDISTREAMING ) //**Yamaha THR10**
{
//p[5]; bInterfaceClass = 255(VENDOR), p[6]; bInterfaceSubClass = 3(MIDI Streaming)
isMidiFound = true; //MIDI device found.
isMidi = true;
}
else
{
#ifdef DEBUG
Serial.print("No MIDI Device\n");
#endif
// buf_ptr += total_length + 1;
// bConfNum = 0;
isMidi = false;
}
break;
always use (uint16_t) cast instead of (uint8_t) cast for epInfo[index].maxPktSize
e.g.
// Extract Max Packet Size from device descriptor
epInfo[0].maxPktSize = (uint16_t)((USB_DEVICE_DESCRIPTOR*)buf)->bMaxPacketSize0;
quick and dirty change for buffersize, that works for THR10 (just a work around, no proper solution, i guess!!!):
if( isMidi )
{
if ((epDesc->bEndpointAddress & 0x80) == 0x80)
{
// Input
index = epDataInIndex;
epInfo[index].epAddr = (epDesc->bEndpointAddress & 0x0F);
//epInfo[index].maxPktSize = (uint16_t)epDesc->wMaxPacketSize;
epInfo[index].maxPktSize = (uint16_t)2048; //necessary for YAMAHA THR10
pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].epAddr, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_IN, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
}
else
{
// Output
index = epDataOutIndex;
epInfo[index].epAddr = (epDesc->bEndpointAddress & 0x0F);
//epInfo[index].maxPktSize = (uint8_t)epDesc->wMaxPacketSize;
epInfo[index].maxPktSize = (uint16_t)2048; //necessary for YAMAHA THR10
pipe = UHD_Pipe_Alloc(bAddress, epInfo[index].epAddr, UOTGHS_HSTPIPCFG_PTYPE_BLK, UOTGHS_HSTPIPCFG_PTOKEN_OUT, epInfo[index].maxPktSize, 0, UOTGHS_HSTPIPCFG_PBK_1_BANK);
}
After that modifikations, i can send System-Exlusive Messages to THR10, like
uint8_t msg1[]= {0xF0,0x43,0x7D,0x30,0x41,0x30,0x01,0x01,0xF7}; //Lamp off
uint8_t msg2[]= {0xF0,0x43,0x7D,0x30,0x41,0x30,0x01,0x00,0xF7}; //Lamp on`
that switches the light of the Guitar-Amp.
But more important, I can send sound-Patches, that are created as a file before with the THR10-Editor on PC.
This way I can build a foot-switch / pedal to change sound patches on the fly like
THR10 foot switch
But this guy did it with an ordinary Arduino Uno and the USB-Host Shield.
With the Due I can use the native USB-Host-Port, have got more memory and speed.
I want to inject Samples to the THR10 with this footswitch as well, as it can also act as IN-/OUT Audio Interface.
EDIT:
After days of research and examination i found out, which delays in "USB.cpp" are necessary (instead of the " #define TRACE_USBHOST(x) x", that solved the issue as well, but gives lots of Serial Prints and slows down everything.)
I would suggest this as a pull request, if i would understand the reason, but without that it is just a kind of work around.
1.) Add a delayMicroseconds(300ul); in function "USBHost::ctrlReq" where the following lines occure:
Code:
if (dataptr != 0)
{
if (direction)
{
// IN transfer
TRACE_USBHOST(printf(" => ctrlData IN\r\n");)
Add here----> delayMicroseconds(300ul); //necessary!! 275ul does not work!!
- Add a delayMicroseconds(120ul); at start of function "USBHost::dispatchPkt"
Code:
uint32_t USBHost::dispatchPkt(uint32_t token, uint32_t hostPipeNum, uint32_t nak_limit)
{
uint32_t timeout = millis() + USB_XFER_TIMEOUT;
uint32_t nak_count = 0;
uint32_t rcode = USB_ERROR_TRANSFER_TIMEOUT;
---> add here: delayMicroseconds(120ul); //NECESSARY!! (100ul does not work!)
TRACE_USBHOST(printf(" => dispatchPkt token=%lu pipe=%lu nak_limit=%lu\r\n", token, hostPipeNum, nak_limit);)
Don't really know w h y this have to be done. But it does nor work otherwise.
;)