flush incoming midi buffer at end of setup

Another observation. This is how the MIDI Clock messages look over time. The timing between clocks is less stable than I would expect.
1699820940327.png

@snowsh Does this pose a problem for you or are you doing some averaging?

Paul
 
OK. So In summary:

It would seem the process of using midi with interrupts must hand off all received messages to the relevant interrupt handler. Whatever library is dealing with this takes all messages buffered in the midi library, and takes over. This is why without the midi.read() loop before we attach the interrupt handlers had no effect. We also see that while(USBmidi.read() {}) had no effect, as already mentioned there is a delay so @PaulStoffregen was correct and indeed the timed loop functions.

Is the fix a bit hacky? maybe. But it does indeed solve the issue. However does this present a problem that may be wider reaching? In any project that uses interrupts do we care about events that have been buffered during setup? I would be keen to understand in more detail how the interrupts are setup. @PaulStoffregen thoughts? Is there anything in the interrupt routines we could call at the end of setup to flush out any buffered events?
 
Last edited:
Likewise, I can confirm that your latest sketch works here. Congrats !! You've successfully found "what" it takes, but now "why" does it work ?? Asking for a friend, of course :) . . .

Mark J Culross
KD5RXT
 
Another observation. This is how the MIDI Clock messages look over time. The timing between clocks is less stable than I would expect.
View attachment 32354
@snowsh Does this pose a problem for you or are you doing some averaging?

Paul
Paul, Yes I have noticed this too. The clock is being generated by a PC with the obvious overheads of a huge OS. In the music world we know that a computer does not provide a rock solid clock, and products exist to address this. One of my pending projects is to offer a stable midi clock. In the real world, these micro differences could be considered a good thing as they give music a more "human feel". Its up to the music producer to decide.
 
OK. So In summary:

The process of using midi with interrupts must hand off all recieved messages to the relevant interrupt handler. Whatever library is dealing with this takes all messages buffered in the midi library, and takes over. This is why without the midi.read() loop before we attach the interuupt handlers had no effect. We also see that while(USBmidi.read() {}) had no effect, as already mentioned there is a delay so @PaulStoffregen was correct and indeed the timed loop functions.

Is the fix a bit hacky? maybe. But it does indeed solve the issue. However does this present a problem that may be wider reaching? In any project that uses interrupts do we care about events that have been buffered during setup? I would be keen to understand in more detail how the interrupts are setup. @PaulStoffregen thoughts? Is there anything in the interrupt routines we could call at the end of setup to flush out any buffered events?
I think there's a bit of confusion over what's happening in the [USB] MIDI interrupt handler. As far as I can see it'll just queue messages until the application is ready for them. The application may attach a callback handler to the event types it wants to deal with, and whenever usbMIDI.read() is called, if there's a handler, then it gets called automatically from within the .read. Alternatively you can query the content of the result and process it, if .read returns true.

The wrinkle here seems to be that there's a gap where .read can return false, implying the pending queue is empty, when this is in fact not the case. Spinning the while() loop for some apparently arbitrary timeout "fixes" this, for a given value of "fixes".

As an aside, it's worth noting that the above means your callback handlers are not executing inside an interrupt - could be important!
 
I had an idea to test this: (!!DONT TRY THIS!!)

in setup use
setup()
{
// Disable USB interrupts temporarily
noInterrupts();

/* rest of the setup code */

interrupts(); // Enable USB interrupts
}

This had the effect of making my teensy un recognisble! Im trying to get it back now using the 15sec trick... hope i havent bricked it. I bricked a nano recently messing around with disabling and enabling interrupts....
 
Last edited:
well I have been checking over everything and this is now working fine. Many thanks everyone especially @kd5rxt-mark @PaulS and of course @PaulStoffregen
TL;DR:
the fix is to use the timed loop before you attach interrupt handlers, and do this at the end of setup:
C++:
setup()
{
    // run setup code

    // at the end of setup:

    elapsedMillis msec = 0;
    while (msec < 250)      // increase this value if needed
    {
        usbMIDI.read();  // consume all recieved MIDI messages for 1/4 second. Increase the timer value if a rush of clocks is experienced at the first loop.
    };

    usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
    // add other interrupt handlers as needed.
 
    // end setup
}

happy days 👌
 
Back
Top