[sdiy] Tools for testing MIDI
brianw
brianw at audiobanshee.com
Thu May 21 03:15:59 CEST 2026
On May 20, 2026, at 4:34 PM, chris wrote:
> On 21/05/2026 00:25, brian wrote:
>> What I recommend is to have two queues: One for System Real Time messages, and another queue for non-real time messages. You can't write the MIDI Clock immediately, unless the serial port is idle, so you need a dedicated queue to hold those timing-critical messages. With this design, your async serial output interrupt can first check the system real time output queue for anything, and prioritize any bytes there. If there's nothing in the real time queue, then the async serial interrupt handler can move on to the non-real time queue for lower priority data.
>>
>> I have not determined how big the System Real Time queue needs to be, but obviously you can get by with only a few bytes. I don't see how you could get hundreds of bytes behind for system real time unless there's something horribly wrong. Nothing will stay in the real time queue for long anyway, since it has top priority. Since many 8-bit MCU chips have limited RAM, saving on queue size is important.
>>
> If you're only sending clock, the second queue may be shrunk down to a simple flag, set by a timer.
Good point. There are so few real time messages that a queue is not needed, per se. A flag is perfect.
> As soon as the send register becomes (or is) available and the flag is set, bam - send a clock byte, and clear the flag.
The timer interrupt handler would check the UART status register and send immediately if the MIDI line is idle, otherwise the clock would be "queued" by setting the bit. The UART send interrupt handler would check the bit and send Clock if it's time for a pulse, clearing the bit before exiting the handler routine.
i.e. If the only MIDI data is Clock (or if there is minimal traffic) then the bit would never be set because the timer interrupt would always find the UART idle and ready to accept a MIDI Clock byte for immediate transmission. This is perhaps a minor optimization, though.
> If there may be other real time messages, a real (but small) queue will be needed.
Since there are fewer than 8 real-time messages, I had considered just using a single byte with 6 flags, one per real-time message. The only caveat is whether it might be possible for more than one real-time message of the same type to get scheduled before the next MIDI byte can be handled. I don't think that's possible; I'll get into the details below.
> However, the flag scheme may be insufficient if the sending system can be busy with lots of things - then it would still be better to send multiple delayed clock messages late than never.
It's wise to consider the possibility of a really busy system, with a backlog of MIDI Clock, but I don't think that could happen. For a clock message to be delayed by more than one byte (320 us), there'd have to be some messages handled with higher priority than MIDI Clock.
You'd have to run the tempo at 7812 bpm to flood the MIDI line, or 3906 bpm if you allow one non-Clock byte between each Clock.
Start, Continue, and Stop should never occur at exactly the same time, so allowing for one between each Clock seems sufficient.
Reset should not have high (timing) priority, so it could be delayed some microseconds without great consequence. This assumes that you even have a Reset button on your device, since the spec says Reset should not be forwarded and should only be manually sent.
I'm assuming that Clock would be top priority; Start/Continue/Stop would share the same priority; and Reset would be the lowest of the real time messages. Given those assumptions, MIDI Clock should never be delayed by more than one whole byte unless other things go terribly wrong. This is because no more than one byte of non-real time MIDI data should ever be sent so long as MIDI Clock has the highest priority (and other real-time should also have higher priority than any non-real time).
On an IBM PC from the 1980s running DOS or Windows, I recall that the operating system actually could not handle 3125 interrupts per second from the UART. With that kind of hardware and OS, you're going to be in trouble. I'm assuming that we're dealing with bare metal firmware that can keep up with MIDI interrupts and timer interrupts with room to spare. That said, if something masks interrupts, or some interrupt handlers consume more than 320 microseconds, then a couple of things would happen: First, the MIDI line would go idle due to starving for data, and, second, MIDI Clocks might get delayed for more than 320 microseconds. When working with even the cheapest Microchip chips, I've never found a system that couldn't handle MIDI. I cut my teeth on the Apple ][ with a 6502 running at 1 MHz, and still didn't trip over busy MIDI traffic. That said, a modern Linux system could easily get bogged down in non-MIDI operations, and if interrupt masks are not managed efficiently then there could be a problem.
Brian
> Chris
More information about the Synth-diy
mailing list