Midipal clock source with higher resolution

Hey, I just bought a Midipal and discovered that the clock can only be set in intervals of 1 bpm. This is a dealbreaker for me because in a live situation I want to be able to do smooth tempo changes, and I consider 1 bpm not smooth. I can program and I can download a toolchain, but it seems that changing the Midipal clock to have a higher accuracy could be a bit problematic since a lot of type definitions will have to be changed etc.

Can you give me any pointers on how to proceed here? I see that I will have to change the files clock and clock_source, but I would be glad if you could give me a quick introduction into the code.

Many thanks, Ander.

Wow, sounds great. As soon as it’s available I will try it out.

Okay… I have an experimental branch of the code in which I toyed with the higher resolution clock idea… It’s now using a timer with a 312.5kHz granularity, which is a 4x improvement in precision over the previous code. It still needs a lot of testing, in particular with respect to all the functions that used clock.value() to do time measurements (bpm counter, tap tempo), and because it changes the way interrupts are handled (there’s one interrupt per clock tick, but it’s heavier, rather than many small interrupts at 78kHz). Other than that it works great and I could integrate your version of the clock app into this branch, it’s in a separate source file (clock_source_hd) which can be built in place of the stock low-res clock app with a define.

I’ll try to get our clock measurement guy (kvitekp) to benchmark the new code and confirm your finding about the 0.5% skew.

Regarding your questions:

  • I added one comment to ui.cc so that I can remember what is happening there in the code. The rest should just be whitespace changes, I did change something there but then changed it back.
  • Ha, completely forgot about the 2300 :slight_smile: I adjusted the factor to calibrate the clock, now the actual bpm is as close to the displayed bpm as I could get it.

Nice work ander. I have no need for this change personally, but I’m really impressed that you were able to do it, and quickly! I think this is what Olivier has had in mind for his work, for people to be able to extend it to their needs!

Two questions:

  • Did you change anything in ui.cc or is it just automatic reformatting from your editor?
  • What is the motivation behind the +2300 in the clock interval computation?

I’ll probably merge this back with the main code and have your version activable by a define.

Ok: https://github.com/wackazong/midipal . Nice programming BTW, I like the way you implemented the app interface via callbacks and hooks. Very easy to make your own extensions.

From what I see now, changing the clock bpm value to a uint16 is really not so trivial… Any pointers really appreciated. I can live with a display that does not display the decimal point and maybe just bp instead of bpm, because the display is too small otherwise.

The clock is obtained by dividing a 78125 Hz master clock, so it wouldn’t be possible to have increments of 0.1 across the 40-240 BPM range. 0.3 or 0.4 is the highest we could aim for, sorry…

I have an idea for a solution that would use the 16-bit timer.

Swap the role of Timer 1 and Timer 2. Use Timer 2 for the 4.9kHz timebase ; and use the compare mode on Timer 1 with an adequate 16 bit threshold to get interrupts at the clock rate (rather than a software divider as currently implemented). You might have to change the prescaler divider on the fly to get a larger range - /8 for the large BPM values and /64 for the lower BPM values - the risk is a loss of precision in the gap.

The catch: no matter how “inaccurate” the clock code is to you, it has been running and tested for months. This is a key element which requires a lot of testing, and I just can’t change it like that and boom, start flashing brand new units with this or let people upgrade to this.

Just to explain what I understood: 240 bpm is 4 beats per second is 96 MIDI clock pulses per second. That makes one MIDI clock pulse per 813.802 master clock pulses (which would be rounded to 814 I suppose). For 239.9 bpm it is 814.141 clock pulses. This would be rounded to the same value. Ok, I see.

But for the range I need (100-130 bpm) it would be possible:

130 bpm is 1502.4 pulses
129.9 bpm 1503.5 pulses

Here, one clock pulse difference lies between 0.1 bpm. Or am I wrong with this calculation?

Let me make my goal more exact then: A MIDI clock source with 0.1 bpm (0.2 bpm is also ok) accuracy between 100 bpm and 130 bpm.

Thanks for your help, Ander.

I missed your last post when I wrote my reply. Switching timers sounds very complicated, and as I have heard that the Midipal clock is indeed very accurate, I think that change would be too big. BTW, I did not want to say that the Midipal clock is not accurate with my topic header, I just used the wrong word. “Resolution” is what I should have typed (changed that just now).

You are correct about your interpretation of the current timer approach and the resolution limitations.

My suggestion would be akin to adaptively jumping to a higher resolution time-base when the clock speed is increased to gain accuracy. The unknown is how the timer reacts when its prescaler is changed on the fly - I fear that this might cause one cycle to get glitchy.

But am I correct when I say that I need to change both clock.cc and clock_source.cc? And how can I display a value like 122.5 in the display?

Yes, you need to change both files.

Add a method in clock.cc to set the tempo from a 8:8 bits value rather than an 8 bits value ; and clock.cc to manage the new UI. The UI and parameter edit system is planned for 8-bits value so you’ll have to work your way around that. You’ll also have to override the bit refreshing the screen to use a special format for the tempo field. There is no existing code for printing values with a decimal point. From a 8:8 bits value you can get the first decimal by using the lower byte x 10 >> 8.

Ok, I will see what I can do. Thanks for your support!

Ok, I did it as specified. Should I upload the code somewhere, and if yes, how?

Do you use github? You could clone the project and host your fork there…

And congratulations!

I would like to be as Ander because I would never be able to solve by myself (or not yet) such problems.

@Olivier: did you then implement the new feature? But, it must be implemented from fabric or all MidiPal could be upgraded via firmware?