Hello. I'm designing a midi sequencer(!) and i'm sending midi clock. I feel it's tight, it doesn't drift, but googling i found someone posted this on the forum:
// The Following is to implement millis() and delay() without messing up with the midi clock interrupt calls //
extern volatile unsigned long timer0_millis;
unsigned long millisNI(void) { return timer0_millis; }
void delayNI(unsigned long ms)
{
unsigned long endtime;
endtime = timer0_millis + ms;
while (((long)endtime - (long)timer0_millis) > 0)
{
;
}
}
That's in the wiring.c file. He says he does it that way so it doesn't mess up with midi clock events. Why would millis() do this? And why does this function make it better and not mess up the clock. I tried it and i didn't notice a change. But it would be nice to know, and if this is a better way, then i would do something like that code... And how could i make it with micros()?
thanks
millis() and micros() both disable interrupts temporarily to make sure the timer variable reading is consistent.
Using this "millisNI()" (NI = no interrupt disabling, I assume) function may yield an incorrect value for timer0_millis. I would strongly recommend against using that function.
The interrupts are disabled for maybe 200us at most (being generous here) if millis() is called. I doubt that makes enough difference in messing up MIDI sequence timing.
Normal millis() turns interrupts off while accessing that variable (timer0_millis). The code you posted doesn't.
It will have the benefit that it is faster and won't turn interrupts off for a few clock cycles, but the disadvantage that the data returned may be incorrect.
See this about critical sections:
It would be OK to call millisNI from inside an interrupt routine (because interrupts are already off).
int2str:
The interrupts are disabled for maybe 200us at most (being generous here) if millis() is called. I doubt that makes enough difference in messing up MIDI sequence timing.
Much less, I would say. About 9 clock cycles, around 562.5 nS.
unsigned long millis()
{
unsigned long m;
uint8_t oldSREG = SREG;
36a: 8f b7 in r24, 0x3f ; 63 (1)
// disable interrupts while we read timer0_millis or we might get an
// inconsistent value (e.g. in the middle of a write to timer0_millis)
cli();
36c: f8 94 cli (1)
m = timer0_millis;
36e: 20 91 2e 01 lds r18, 0x012E (2)
372: 30 91 2f 01 lds r19, 0x012F (2)
376: 40 91 30 01 lds r20, 0x0130 (2)
37a: 50 91 31 01 lds r21, 0x0131 (2)
SREG = oldSREG;
37e: 8f bf out 0x3f, r24 ; 63 (1)
return m;
}
380: b9 01 movw r22, r18 (1)
382: ca 01 movw r24, r20 (1)
384: 08 95 ret (4)
Thanks. Well, even 200us is very little... At a very fast tempo, let's say, 240bpm, this is 1/4 note every 250ms. Midi clock sends 24 pulses every 1/4, so i'm sending a pulse every 10.41ms. I shouldn't have a problem then? Actually, i think i don't have. The program which i send the midi clock to, always is at a fixed bpm, so the count is tight. And also i measured it with an oscilloscope and it was pretty well i think, for 8 or 10 1/4 or 1/8 1/16 i had very little error, +/- 2ms at most... If itsn't broken i shouldn't fix it then? It's good to know though, and i didn't know what the NI meant.
thanks