[sdiy] Bunching of MIDI clock messages

rsdio at sounds.wa.com rsdio at sounds.wa.com
Thu Sep 12 21:23:16 CEST 2013

I have to disagree with one part of Neil's suggestion, even though I  
agree in general.

I've written a great deal of firmware with interrupt handlers, and  
you certainly want to use "male shopping tactics" (love that  
dysphemism). However, I'd also like to allude to that quote  
attributed to Einstein, where he suggested to keep things "as simple  
as possible, but no simpler." In that light, I say that:

Interrupt routines should do as little as is necessary, but no less.

In this case, it's necessary to process Real-Time MIDI messages  
a.s.a.p., which means they must be handled in the interrupt - at  
least the critical parts. Thankfully, the MIDI protocol was designed  
with the understanding of how it would be implemented, and thus it's  
dead simple to detect Real-Time messages. Just mask out the upper 5  
bits of each byte, and if all bits are set then it's a Real-Time  
message. The interrupt routine code should be able to make this test  
in fewer cycles than it takes to store the byte in a buffer, and  
that's true even with 8-bit CPU chips from the 1980s. Basically, the  
interrupt routine would have two parts; one for Real-Time and the  
second half for all other messages.

But in keeping with your rule of keeping interrupt handlers fast,  
this then becomes a question of how you implement the code. When  
designing the buffer, the clock, active sensing, and all other  
aspects that are touched in the interrupt, the code must be designed  
to make the interrupt routine run fast. For examples:

A) Active Sensing is probably a counter that it decremented over  
time, restored to a maximum count when Active Sensing is received,  
and set up to kill all MIDI Notes if the counter runs out. The Real- 
Time section of the interrupt really only needs to store the maximum  
count into a data structure or register and then get out. This  
implementation fits within the rules for interrupt routines.

B) The buffer for MIDI data should not be a C++ object, and it  
particularly should not allocate memory when the buffer overflows.  
The MIDI buffer should be an efficient structure that can have data  
added in as few cycles as possible by the interrupt routine. The code  
to pull data out of the buffer is not so critical, but the interrupt  
code should be efficient.

C) The internal sequencer clock is very timing sensitive, so it will  
probably be implemented by a timer peripheral (vintage synths used an  
external timer chip, modern CPU chips have the timer peripheral built  
in). The interrupt routine should probably test for a clock message  
as soon as it determines that it has received a Real-Time message,  
and then the interrupt code should read the timer counter register  
and save it away somewhere. It's not necessary to actually calculate  
any adjustments based on the MIDI clock message inside the interrupt,  
but it is critical that the timing be checked against the reference  
during the interrupt. If you put the Real-Time MIDI Clock byte in a  
buffer and then check the timing when you pull the byte out of the  
buffer, then it will be too late for an accurate measurement of when  
the MIDI Clock arrived.

In other words, the interrupt routine should do one very basic step  
of MIDI data parsing - determining whether a byte is real-time or not  
- but then it's possible to leave the subsequent steps of MIDI  
parsing to the routing that is pulling the data out of the buffer.  
Theoretically, all MIDI parsing could be handled in the interrupt  
with careful coding, but I won't say that it's necessary. Only the  
real-time parsing is necessary in the interrupt.

Note that I sort of agree with your assertion that there is no reason  
to use polling, except that I think that you've overlooked something  
with regard to the definition of polling. If you fill a buffer in an  
interrupt routine, and pull MIDI data out of that buffer in normal  
mode, then all of that normal code is technically polling the buffer.  
The normal code must read the semaphores and buffer pointers to  
detect when data has arrived, and that is the definition of polling.  
To clarify, it's not the same as polling the hardware itself, e.g.  
the UART registers, but it's still polling.

By the way, the rest of Neil's suggestions about a software PLL for  
the MIDI clock are dead on.

Brian Willoughby
Sound Consulting

On Sep 12, 2013, at 05:42, Neil Johnson wrote:
> Firstly, minimise processing in interrupt handlers.  Interrupt
> handlers should follow male shopping tactics: get in, get it, get out
> FAST!  Get the received byte out of the UART, store it in a buffer,
> and bump a semaphore.  Any MIDI data parsing should be done on the
> other side of the buffer in normal mode.  There is no reason this has
> to be slow, and no reason to use polling.

More information about the Synth-diy mailing list