|
|
View previous topic :: View next topic |
Author |
Message |
dvdb
Joined: 12 Jan 2004 Posts: 6 Location: Brussels, Belgium
|
Solution for zero jitter interrupt code for 18F pics |
Posted: Mon Dec 20, 2004 1:25 pm |
|
|
I am using a 18F that runs a time critical task based on timer0 that is running at the same rate as the program counter.
The intervals between actions taken some time after rollover of timer0 are critical, and interrupt driven.
To allow for some short time disables of interrupts in the main code (eg. for the internal EEPROM writing sequence) I synchonise timer0 so that it interrupts early, and then let the interrupt service code wait until timer0 reaches some predefined value.
But: here's the catch: the loop that checks timer0 obviosly generates a jitter of an amplitude that almost equals the loop time.
Eg. this simple approach (code added to measure jitter)
Code: | min=255;max=0;
SETUP_TIMER_0 (RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_BIT);
for (cnt2=0;cnt2<20;cnt2++){
set_timer0(cnt2);
do{}while(get_timer0()<50);
cnt=get_timer0();
if(cnt<min){min=cnt;} //keep minimum timer value
if(cnt>max){max=cnt;} //keep max timer value
};
while(true){}; //wait for user |
will give min=61, max=72.
I'd like to share a solution that allows zero jitter, provided some ASM:
Code: | for (cnt2=0;cnt2<20;cnt2++){
set_timer0(cnt2);
#ASM
movf PCL,0 //update PCLATH and PCLATU for calculated jump
wait: //fairly straightforward waiting loop
MOVF 0xFD6,W //load timer 1
ADDLW 0xFF-40 //add offset
BNC wait //wait further until timer>0x40
//now the exact synchronising part
rlncf WREG,0 //double w first before calculated jump
addwf PCL,1 //calculated branch; 1 means store result in register
NOP
NOP
NOP
#endasm
cnt=get_timer0();
if(cnt<min){min=cnt;}
if(cnt>max){max=cnt;}
};
|
-> mix=max=50!, no jitter.
The idea is to jump further if timer0 is higher.
Two caveats, however:
1. the calculated jump should not cross a page boundary (unlikely but possible, so check)
BTW anybody knows how to have this checked by the compiler?
2. the ASM part should not be entered with the timer already too high, if not the calculated jump will be erratic. If not sure check before the ASM part.
Anybody has better ideas to synchronise code exactly to a timer? _________________ Dirk Van den Berge |
|
|
yerpa
Joined: 19 Feb 2004 Posts: 58 Location: Wisconsin
|
Zero jitter interrupt code |
Posted: Fri Feb 11, 2005 1:45 pm |
|
|
Here is some code that worked for me on an audio application using PIC 16F876. It is not original, but I don't remember where I first found it. It worked well for the audio application with sample rate of 11 KHz.
Code: | // INTERRUPT ROUTINE FOR RTCC...
#INT_RTCC
void time0_handler(void)
{
#asm
sync: btfss 1, 3 //Synchronize (de-jitter) the samples.
goto sync
btfss 1, 0
nop
#endasm
PORTB=sample; // Write sample to DAC.
RTCC=0x4f;
|
|
|
|
dvdb
Joined: 12 Jan 2004 Posts: 6 Location: Brussels, Belgium
|
Interesting, but how can it work |
Posted: Fri Feb 11, 2005 3:38 pm |
|
|
I suppose some construction like yours should exist, but this particular one I have some difficulty with:
The first part: Quote: | sync: btfss 1, 3 //Synchronize (de-jitter) the samples.
goto sync
|
is still a loop that executes 1..n times, never 1.5 times. Since the loop time is 3 cycles, at least 2 cycles worth of jitter should remain.
The second part
can't work because it always executes in 2 cycles, regardless of the btfss skipping or not (it doesn't make a difference wether the NOP is executed or not)
So, on first sight, it doesn't appear to be able to produce zero jitter, but on occasion I'll test it, just out of curiosity. _________________ Dirk Van den Berge |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|