void TestTimer0Jump(void)
{
byte k;
gSpmSequenceAddr=0xff;
while((volatile byte)gFrameSyncState!=kFrameSyncBotMargin)
; // wait for bottom sync. No other interrupts will happen for about 3.5ms.
asm volatile(
"push r16\n"
"ldi r16,1\n" // timer 0 start at fClk
"out %0,r16\n" // set TCCR0B so off we go. This is 1c.
// 40c later we should get an interrupt, but when precisely?
"rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n"
"1:rjmp 1f\n" // 30c so far
"1:ldi r16,0\n" // Use r16 value to determine where interrupt takes place
"ldi r16,1\n"
"ldi r16,2\n"
"ldi r16,3\n"
"ldi r16,4\n"
"ldi r16,5\n"
"ldi r16,6\n"
"ldi r16,7\n"
"ldi r16,8\n"
"ldi r16,9\n" // 40c should have happened by now.
"ldi r16,10\n"
"ldi r16,11\n" // **************
"ldi r16,12\n"
"ldi r16,13\n"
"ldi r16,14\n" // at some point here we've returned from the interrupt.
"ldi r16,15\n"
"ldi r16,16\n"
"ldi r16,17\n"
"ldi r16,18\n"
"ldi r16,19\n"
"ldi r16,20\n" // 50c should really have happened by now!
"ldi r16,0\n"
"out %0,r16\n" // stop the clock
"pop r16\n" : : "I" (kTCCR0B));
DotQuotePgm(TestTimer0JumpMsg);
DotHex((volatile ushort)gSpmSequenceAddr);
k=Key();
}
ISR(__vector_15) // OCR0B
{
asm volatile(
"sts %0,r16\n"
"ldi r16,0\n"
"out %0,r16\n" // stop timer 0
: : "g" (gSpmSequenceAddr));
}
I used SetupTimer0B(40) to set it up called TestTimer0Jump and at the end, gSpmSequenceAddr contains the last value of r16 loaded. So, then you know exactly how many execution cycles after Timer0 started corresponded to OCR0B=40. It turned out it was 42 execution cycles (comment marked *************).
That was the answer.
Ironically, the actual code itself ended up with a timer setting of 40 - an amazing guess huh?