Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 10 of 10

Thread: MIDI SendSysEx on USB host

  1. #1
    Junior Member
    Join Date
    Feb 2019
    Location
    Switzerland
    Posts
    6

    MIDI SendSysEx on USB host

    Hi. I'm trying to achieve something similar to the THR_Footswitch by Mathis Rosenhauer (LINK) but with a Teensy 3.6 and its second USB port. The THR10 guitar amplifier is a MIDI Device, so the Teensy must act as an USB host. The THR10 will be the only device that is connected to the Teensy. All that is missing is the implementation of my SendToMidi() method, which shall be able to send an array of bytes of any size like this:

    bool SendToMidi(byte[] byteArray, int nLength)
    {
    // Use SendSysEx to send byteArray to the THR10 over USB
    }

    Currently, I only want to send SysEx-Data and not receive anything. I am aware of USBHost_t36, but I wasn't able to find an example for this (presumably) simple task. Can anybody show me how to

    - Setup() USB MIDI for the second USB port
    - Implement the beforementioned SendToMidi() function

    Any help is highly appreciated.

    Karl

  2. #2
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,263
    In Arduino, click File > Examples > USBHost_t36 > MIDI > Interface_16x16.

    Admittedly this is a long and somewhat complex example, because it allows 16 MIDI ports on your PC to communicate with 6 serial (5 pin DIN) MIDI devices and up to 10 more USB MIDI devices plugged into hubs on the host port. Look for this line, which sends to one of the 10 devices on the host port.

    Code:
            default: // cases 6-15
              midilist[cable - 6]->sendSysEx(SysExLength, usbMIDI.getSysExArray(), true);
    USB host uses the same MIDI functions as the MIDI library and USB device MIDI. If you've only created 1 "MIDIDevice" instance (rather than 10 plus several hubs as the example does), because you only wish to support 1 device plugging into the host port, then you won't need to bother with an array of pointers. You can just use the name directly, like...

    Code:
      midi01.sendSysEx(length, messageData, true);
    The "length" is how many bytes are in your message, messageData is the array holding those bytes, and the last true/false tells whether your data already has the sysex begin & end bytes (if you give false, the library adds them for you).

    It's always safe to send message to your MIDIDevice object. If the user hasn't actually plugged in a MIDI device to the host port, it will simply do nothing and discard the data (pretty much the same as sending to a regular serial MIDI port where nothing is plugged in).

  3. #3
    Junior Member
    Join Date
    Feb 2019
    Location
    Switzerland
    Posts
    6
    Thank you very much, Paul. This clears things up quite a bit.

    In his code, Mathis Rosenhauer sends a prefix, then the actual patch data and lastly a suffix with a checksum and an end-byte like this:

    Code:
    void send_patch(uint8_t patch_id)
    {
        uint8_t prefix[] = 
        {
            0xf0, 0x43, 0x7d, 0x00, 0x02, 0x0c, 0x44, 0x54,
            0x41, 0x31, 0x41, 0x6c, 0x6c, 0x50, 0x00, 0x00,
            0x7f, 0x7f
        };
    
        uint8_t cs = 0x71; // prefix checksum
    
        Midi.SendSysEx(prefix, sizeof(prefix));
    
        // Mathis uses a loop to split the patch data into chunks of 16 bytes, sends each chunk and updates the checksum cs
        // for each chunk individually, but basically, he just sends out the entire 261 bytes of the patch
        Midi.SendSysEx(chunk, sizeof(chunk));
    
        // Calculate check sum.
        suffix[0] = (~cs + 1) & 0x7f;
    
        // end SysEx
        suffix[1] = 0xf7;
        Midi.SendSysEx(suffix, sizeof(suffix));
    }
    Can I assume that, if I use midi01.sendSysEx(length, messageData, true), sendSysEx() will create this exact same prefix and suffix for me?

    Cheers,
    Karl

  4. #4
    Junior Member
    Join Date
    Feb 2019
    Location
    Switzerland
    Posts
    6
    Quote Originally Posted by Hirnilein0815 View Post
    Can I assume that, if I use midi01.sendSysEx(length, messageData, true), sendSysEx() will create this exact same prefix and suffix for me?
    I meant midi01.sendSysEx(length, messageData, false), off course.

  5. #5
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,263
    The 3rd true/false parameter merely tells if you have already put 0xF0 in the first byte and 0xF7 in the last byte in your data array. It's really that simple.

    This code fragment you've show sends 3 sysex messages. The true/false applied separately to each one. The first definitely has 0xF0 and 0xF7, so you would use "true". The other 2 presumably have these too, though this code depends on other variables not declared in the small fragment you showed, so that's just my assumption.

    The true/false parameter is provided as a convenience, since some people prefer to write their code to create only the data part of the sysex message, omitting the leading 0xF0 and 0xF7.

    This parameter is something completely separate from the use of 3 messages, prefix, data, checksum. As far as USBHost_t36 is concerned, this is just 3 individual sysex messages. The library doesn't know or care that these 3 messages are related. The 3rd true/false does NOT have anything to do with use of multiple messages. It applies only to each individual message.

    For example, if you wanted, you could transmit the prefix with that code, where 0xF0 & 0xF7 are already in the array using "true". Then if you happen to have only the data in an array, you could transmit it with "false" if you wanted to avoid the extra step of putting 0xF0 in the first byte of your array and 0x7F in the last byte. Likewise, you could send the checksum message either way, because the true/false parameter is for each individual message.

    As far as the library is concerned, it's just 3 separate & independent sysex messages. The fact that these 3 message go together and mean something as a group of 3 is up to your program. The library just handle them as 3 completely separate messages.

  6. #6
    Junior Member
    Join Date
    Feb 2019
    Location
    Switzerland
    Posts
    6
    Thanks a lot, Paul. I think, I got it now. The prefix and suffix Mathis sent out in his code are not part of the MIDI protocol, as I assumed, but specific to the THR10 (except for the leading 0xF0 and the trailing 0xF7). I'll have to send out exactly the same data as Mathis, but I will probably send out all data at once from one large array and not in multiple steps. I'll report when I'm done.

  7. #7
    Junior Member
    Join Date
    Feb 2019
    Location
    Switzerland
    Posts
    6
    I managed to test my USB Host Connection with the InputFunctions example. I receive MIDI events when I use a MIDI keyboard. But I don't receive anything when I connect the THR10 instead.
    When I run a MIDI monitor on my Windows PC, I see tons of events from the THR10, so I know that it is continuously sendig out MIDI SysEx commands. Any ideas why the Teensy doesn't see them?

  8. #8
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,263
    Is the THR10 a USB device or USB host? Can you give more detailed info or photos?

  9. #9
    Junior Member
    Join Date
    Feb 2019
    Location
    Switzerland
    Posts
    6
    The THR10 is a device. It has the same female USB-B connector as most MIDI controllers, like this one. Mathis Rosenhauer was using the Arduino USB Host Shield in his project. The THR10 is usually connected to a computer in order to use the software editor that Yamaha provides.

    Some smart people found out that the THR10 is using standard MIDI SysEx (and only SysEx) for all communication between the software editor and the device. Every aspect can be controlled via MIDI.
    https://www.thegearpage.net/board/in...editor.1669012
    https://drive.google.com/file/d/0ByM...VPSkhkelk/view

    Can you confirm that InputFunctions example should also show some output for SysEx messages and not only for known MIDI commands like note-on etc.?

  10. #10
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    19,263
    Quote Originally Posted by Hirnilein0815 View Post
    Can you confirm that InputFunctions example should also show some output for SysEx messages and not only for known MIDI commands like note-on etc.?
    Yes, it should.

    In fact, there are 2 different sysex handlers.

    Code:
      // 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);
    Maybe try editing the code so only 1 of these lines is used. Hopefully at least 1 of them will work.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •