[sdiy] MIDI Clock sync advice

brianw brianw at audiobanshee.com
Sat Mar 9 03:20:43 CET 2024


I have a hunch that PLL and PID might come in handy. I do not have direct experience designing either one, but I'll try to describe what I (think I) understand, and maybe others can contribute. In particular, maybe "DIY DSP" can summarize software PLL and Kalman filters.


PLL

My understanding is that both analog and digital PLL convert the signals to digital before feeding the circuit that compares them. Thus, there are only rising edges and falling edges. If the local oscillator edge arrives first, then its frequency is too high, so the control signal (maybe CV) is changed in a small increment to lower the generated frequency. However, if the remote oscillator edge arrives first, then the local oscillator frequency is too low, so the CV is changed in a small increment to raise the generated frequency. One side effect of this is that not only does the frequency change until the two oscillators match, but their phase also matches. For DPLL, I seem to recall that the comparison circuit is an exclusive-OR gate.

The small incremental changes in the local frequency could be as simple as incrementing or decrementing the timer count that restarts the period. I think that might be all that's needed to implement a PLL, although there might be some details regarding when the timer updates its registers and counters.

One thing I'm not sure about is that a hardware PLL seems like it would adjust the frequency twice per period, on both rising and falling edges. However, I'm not sure how the comparison circuit decides which input is ahead or behind, especially since the logic would be opposite for rising edges versus falling edges.

When using a timer peripheral to implement PLL, you'll have at least one interrupt per sequencer clock. I've even seen some timer designs that allow a second interrupt in the middle of the period, with control over where that second interrupt occurs. One nice thing is that timer peripherals often update their period with every interrupt, so you can build a period that is not 50/50% duty cycle by changing the period to alternate between two values. i.e. you can string together a sequence of unrelated periods to build a complex waveform (which I've done for LED brightness manipulations).

The other (second) timer will probably just count time, and the MIDI input interrupt would just read the count from the timer whenever a MIDI System Real Time message arrives. The timer counter can then be reset to measure the time elapsed until the next message arrives. These values will surely have some jitter, but that will be handled - either by filtering that is part of the PLL or perhaps some other way. It's definitely true that filtering the feedback part of the PLL affects its performance.


PID

Proportional / Integral / Derivative - My understanding of these control systems is that it might be possible to have a different response to large changes versus small changes. When the MIDI clock first starts, or the tempo is changed by the user, then there would be a large change in any PLL that implements clock sync. At those times, it's most beneficial if the PLL jumps quickly to the new rate. During normal operations, the input clock should be relatively stable, apart from any jitter. For these conditions, the PLL should smooth out any minor differences in the measured period durations, such that the local clock runs at the "long term average" rate of the incoming clock. Of course, "long term" is relative.

The people that I've talked to who are experts in PID still seem to treat it as a black art that is poorly understood. Perhaps I've just not met anyone who really understands the math. It certainly seems to be the case that engineers just poke various P, I, and D weights into the formula. I've also seen some implementations that seem to insert a layer of indirection between the PID calculations and the actual control, but that somehow seems like it would defeat the purpose.

In any case, it seems like a PID controller could both deal with jitter in the period measurements of the incoming MIDI clock, as well as adapt quickly to abrupt changes in tempo that should flush the filter and quickly restart a new average.


If anyone else wants to jump in and explain these common but mysterious engineering tools, it would surely be appreciated.

Brian


On Mar 8, 2024, at 3:29 PM, Tom Wiltshire wrote:
> Yes, that's a very useful sanity check because that's pretty much what I'd been thinking about too.
> 
> As you say, you have to have one timer peripheral generating the "pulses" in the "Pulses per quarter note". These are then counted up to create swing/shuffle/output the current beat/whatever. Changing the timing of this timer alters the tempo. This timer variable is the ultimate destination required for our MIDI sync.
> 
> At the same time, you need something that is keeping track of how long has passed since the last MIDI Clock pulse. That's going to be *another* timer peripheral, prescaled to to give you a good number of counts for likely tempos. There's no point counting 64MHz clock pulses with a 16-bit timer if it's going to overflow five times before you even get your next pulse. Equally, you don't want to lose resolution by finishing up with counts of only a few dozen for typical tempos. If realistic tempos are in the range 30BPM to 300BPM (a decade) then we'd ideally like those tempos to give timer results between (say) 60,000 and 6000 for a 16-bit timer. Reality will intrude here and we'll take whatever we can get that's closest, but that's the general idea.
> 
> My proposed next step would be to then add some filtering to those timing results, since I suspect because of the vagaries of MIDI they won't be that tight. Maybe you get 7819, 7847, 7799, etc - maybe it's worse than that? So feed the results into a simple IIR (probably based on shifts rather than anything more complicated) and then use the result.

In this case, PID processing might help more than a single filter.

> The output from the filter is a time-period measured in master-clock-ticks-divided-by-x (we don't know what x needs to be yet because I haven't worked it out). That time period might then need to be converted into a count value for the Tempo timer. If they're both running with the same clock and prescale value, that's trivial, but there might be some little adjustment to make.

Because the frequency resolution of a timer is very coarse at low frequencies, and much higher resolution at high frequencies, I suspect that there might be some benefit to tracking the frequency in a way that maintains resolution across the whole frequency range in some state variable, and then only convert to timer period as the final step.

> Tom
> 
> On 8 Mar 2024, at 23:06, brianw <brianw at audiobanshee.com> wrote:
>> Here's a quick thought:
>> 
>> You might use two timer peripherals on the PIC18F. Both would be fed from the same master clock source, but each might have different pre-dividers and periods.
>> 
>> One would implement the sequencer clock, and would not necessarily be anchored to anything but the incoming MIDI clock. As tempo changes, this timer would vary in speed.
>> 
>> The other timer would run 8 to 16 times higher resolution, perhaps more, and this would be a local time reference. This second timer would be how you measure the time between incoming MIDI messages, and thus it would measure the incoming clock rate. This timer would never change because it's the reference for measuring other things. Like a real-time wall clock, but hopefully more accurate. The period has to be fast enough to detect slight changes in the incoming MIDI clock.
>> 
>> Brian
>> 
>> On Mar 8, 2024, at 2:59 PM, brian wrote:
>>> PLLs are still a bit of a mystery to me, including software and hardware PLL and DPLL.
>>> 
>>> That said, any successful implementation would probably have some sort of hardware timing reference that gets tweaked from software. Basically, the solution will not be pure software, and thus the solution will depend upon the timing hardware that you have. You mentioned the PIC18F in another message, and that chip has several timers. I'm fairly certain that your sequencer timing would be based on one (or more?) hardware timer peripherals, and then the "PLL" would tweak the period of that timer.
>>> 
>>> I'll have more to say in reply to your message about the PIC18F platform...
>>> 
>>> Brian
>>> 
>>> On Mar 8, 2024, at 2:36 PM, Tom Wiltshire wrote:
>>>> Thanks. Do you have any resources to point to that I could look up about software PLLs? All the stuff I've seen seems to assume it's a hardware solution. While some of that is clearly transferable, something that had software in mind would help a lot.
>>>> 
>>>> Tom
>>>> 
>>>> On 8 Mar 2024, at 16:52, DIY DSP wrote:
>>>>> I've done this the "easy" way with a software PLL, and the hard way with a Kalman filter.  
>>>>> Technically what you need depends on the noise/error profile of the source clock.
>>>>> But start with the software PLL.. On every 4th input clock, use the error to update the phase and period of the output clock.
>>>>> For this application, since the signals will converge very quickly relative to how often they chance, I recommend using only the P term from the PID to compute the error and reset the phase of the output clock on the spot to the input clock.
>>>>> 
>>>>> Noah Vawter's futuristic electronic music instrument lab: youtube.com/diydsp




More information about the Synth-diy mailing list