Main Page   Modules   Data Structures   File List   Data Fields   Globals  

timer.c

Go to the documentation of this file.
00001 /*! \file timer.c \brief System Timer function library. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'timer.c'
00005 // Title        : System Timer function library
00006 // Author       : Pascal Stang - Copyright (C) 2000-2002
00007 // Created      : 11/22/2000
00008 // Revised      : 07/09/2003
00009 // Version      : 1.1
00010 // Target MCU   : Atmel AVR Series
00011 // Editor Tabs  : 4
00012 //
00013 // This code is distributed under the GNU Public License
00014 //      which can be found at http://www.gnu.org/licenses/gpl.txt
00015 //
00016 //*****************************************************************************
00017 
00018 #ifndef WIN32
00019     #include <avr/io.h>
00020     #include <avr/signal.h>
00021     #include <avr/interrupt.h>
00022     #include <avr/pgmspace.h>
00023     #include <avr/sleep.h>
00024 #endif
00025 
00026 #include "global.h"
00027 #include "timer.h"
00028 
00029 // Program ROM constants
00030 // the prescale division values stored in 2^n format
00031 // STOP, CLK, CLK/8, CLK/64, CLK/256, CLK/1024
00032 unsigned char __attribute__ ((progmem)) TimerPrescaleFactor[] = {0,0,3,6,8,10};
00033 // the prescale division values stored in 2^n format
00034 // STOP, CLK, CLK/8, CLK/32, CLK/64, CLK/128, CLK/256, CLK/1024
00035 unsigned char __attribute__ ((progmem)) TimerRTCPrescaleFactor[] = {0,0,3,5,6,7,8,10};
00036 
00037 
00038 // Global variables
00039 // time registers
00040 volatile unsigned long TimerPauseReg;
00041 volatile unsigned long Timer0Reg0;
00042 volatile unsigned long Timer2Reg0;
00043 
00044 typedef void (*voidFuncPtr)(void);
00045 volatile static voidFuncPtr TimerIntFunc[TIMER_NUM_INTERRUPTS];
00046 
00047 // delay for a minimum of <us> microseconds 
00048 // the time resolution is dependent on the time the loop takes 
00049 // e.g. with 4Mhz and 5 cycles per loop, the resolution is 1.25 us 
00050 void delay(unsigned short us) 
00051 {
00052     unsigned short delay_loops;
00053     register unsigned short i;
00054 
00055     delay_loops = (us+3)/5*CYCLES_PER_US; // +3 for rounding up (dirty) 
00056 
00057     // one loop takes 5 cpu cycles 
00058     for (i=0; i < delay_loops; i++) {};
00059 } 
00060 
00061 void timerInit(void)
00062 {
00063     u08 intNum;
00064     // detach all user functions from interrupts
00065     for(intNum=0; intNum<TIMER_NUM_INTERRUPTS; intNum++)
00066         timerDetach(intNum);
00067 
00068     // initialize all timers
00069     timer0Init();
00070     timer1Init();
00071     #ifdef TCNT2    // support timer2 only if it exists
00072     timer2Init();
00073     #endif
00074     // enable interrupts
00075     sei();
00076 }
00077 
00078 void timer0Init()
00079 {
00080     // initialize timer 0
00081     timer0SetPrescaler( TIMER0PRESCALE );   // set prescaler
00082     outp(0, TCNT0);                         // reset TCNT0
00083     sbi(TIMSK, TOIE0);                      // enable TCNT0 overflow interrupt
00084 
00085     timer0ClearOverflowCount();             // initialize time registers
00086 }
00087 
00088 void timer1Init(void)
00089 {
00090     // initialize timer 1
00091     timer1SetPrescaler( TIMER1PRESCALE );   // set prescaler
00092     outp(0, TCNT1H);                        // reset TCNT1
00093     outp(0, TCNT1L);
00094     sbi(TIMSK, TOIE1);                      // enable TCNT1 overflow
00095 }
00096 
00097 #ifdef TCNT2    // support timer2 only if it exists
00098 void timer2Init(void)
00099 {
00100     // initialize timer 2
00101     timer2SetPrescaler( TIMER2PRESCALE );   // set prescaler
00102     outp(0, TCNT2);                         // reset TCNT2
00103     sbi(TIMSK, TOIE2);                      // enable TCNT2 overflow
00104 
00105     timer2ClearOverflowCount();             // initialize time registers
00106 }
00107 #endif
00108 
00109 void timer0SetPrescaler(u08 prescale)
00110 {
00111     // set prescaler on timer 0
00112     outp( (inp(TCCR0) & ~TIMER_PRESCALE_MASK) | prescale, TCCR0);
00113 }
00114 
00115 void timer1SetPrescaler(u08 prescale)
00116 {
00117     // set prescaler on timer 1
00118     outp( (inp(TCCR1B) & ~TIMER_PRESCALE_MASK) | prescale, TCCR1B);
00119 }
00120 
00121 #ifdef TCNT2    // support timer2 only if it exists
00122 void timer2SetPrescaler(u08 prescale)
00123 {
00124     // set prescaler on timer 2
00125     outp( (inp(TCCR2) & ~TIMER_PRESCALE_MASK) | prescale, TCCR2);
00126 }
00127 #endif
00128 
00129 void timerAttach(u08 interruptNum, void (*userFunc)(void) )
00130 {
00131     // make sure the interrupt number is within bounds
00132     if(interruptNum < TIMER_NUM_INTERRUPTS)
00133     {
00134         // set the interrupt function to run
00135         // the supplied user's function
00136         TimerIntFunc[interruptNum] = userFunc;
00137     }
00138 }
00139 
00140 void timerDetach(u08 interruptNum)
00141 {
00142     // make sure the interrupt number is within bounds
00143     if(interruptNum < TIMER_NUM_INTERRUPTS)
00144     {
00145         // set the interrupt function to run nothing
00146         TimerIntFunc[interruptNum] = 0;
00147     }
00148 }
00149 /*
00150 u32 timerMsToTics(u16 ms)
00151 {
00152     // calculate the prescaler division rate
00153     u16 prescaleDiv = 1<<(PRG_RDB(TimerPrescaleFactor+inp(TCCR0)));
00154     // calculate the number of timer tics in x milliseconds
00155     return (ms*(F_CPU/(prescaleDiv*256)))/1000;
00156 }
00157 
00158 u16 timerTicsToMs(u32 tics)
00159 {
00160     // calculate the prescaler division rate
00161     u16 prescaleDiv = 1<<(PRG_RDB(TimerPrescaleFactor+inp(TCCR0)));
00162     // calculate the number of milliseconds in x timer tics
00163     return (tics*1000*(prescaleDiv*256))/F_CPU;
00164 }
00165 */
00166 void timerPause(unsigned short pause_ms)
00167 {
00168     // pauses for exactly <pause_ms> number of milliseconds
00169     u08 timerThres;
00170     u32 ticRateHz;
00171     u32 pause;
00172 
00173     // capture current pause timer value
00174     timerThres = inb(TCNT0);
00175     // reset pause timer overflow count
00176     TimerPauseReg = 0;
00177     // calculate delay for [pause_ms] milliseconds
00178     // prescaler division = 1<<(PRG_RDB(TimerPrescaleFactor+inp(TCCR0)))
00179     ticRateHz = F_CPU/(1<<(PRG_RDB(TimerPrescaleFactor+inp(TCCR0))));
00180     // precision management
00181     if( ticRateHz > 1000000)
00182         pause = pause_ms*(ticRateHz/1000);
00183     else
00184         pause = (pause_ms*ticRateHz)/1000;
00185     
00186     // loop until time expires
00187     while( ((TimerPauseReg<<8) | inb(TCNT0)) < (pause+timerThres) )
00188     {
00189         if( TimerPauseReg < (pause>>8));
00190         {
00191             // save power by idling the processor
00192             set_sleep_mode(SLEEP_MODE_IDLE);
00193             sleep_mode();
00194         }
00195     }
00196 
00197     /* old inaccurate code, for reference
00198     
00199     // calculate delay for [pause_ms] milliseconds
00200     u16 prescaleDiv = 1<<(PRG_RDB(TimerPrescaleFactor+inp(TCCR0)));
00201     u32 pause = (pause_ms*(F_CPU/(prescaleDiv*256)))/1000;
00202     
00203     TimerPauseReg = 0;
00204     while(TimerPauseReg < pause);
00205 
00206     */
00207 }
00208 
00209 void timer0ClearOverflowCount(void)
00210 {
00211     // clear the timer overflow counter registers
00212     Timer0Reg0 = 0; // initialize time registers
00213 }
00214 
00215 long timer0GetOverflowCount(void)
00216 {
00217     // return the current timer overflow count
00218     // (this is since the last timer0ClearOverflowCount() command was called)
00219     return Timer0Reg0;
00220 }
00221 
00222 #ifdef TCNT2    // support timer2 only if it exists
00223 void timer2ClearOverflowCount(void)
00224 {
00225     // clear the timer overflow counter registers
00226     Timer2Reg0 = 0; // initialize time registers
00227 }
00228 
00229 long timer2GetOverflowCount(void)
00230 {
00231     // return the current timer overflow count
00232     // (this is since the last timer2ClearOverflowCount() command was called)
00233     return Timer2Reg0;
00234 }
00235 #endif
00236 
00237 void timer1PWMInit(u08 bitRes)
00238 {
00239     // configures timer1 for use with PWM output
00240     // on OC1A and OC1B pins
00241 
00242     // enable timer1 as 8,9,10bit PWM
00243     if(bitRes == 9)
00244     {   // 9bit mode
00245         sbi(TCCR1A,PWM11);
00246         cbi(TCCR1A,PWM10);
00247     }
00248     else if( bitRes == 10 )
00249     {   // 10bit mode
00250         sbi(TCCR1A,PWM11);
00251         sbi(TCCR1A,PWM10);
00252     }
00253     else
00254     {   // default 8bit mode
00255         cbi(TCCR1A,PWM11);
00256         sbi(TCCR1A,PWM10);
00257     }
00258 
00259     // clear output compare value A
00260     outp(0, OCR1AH);
00261     outp(0, OCR1AL);
00262     // clear output compare value B
00263     outp(0, OCR1BH);
00264     outp(0, OCR1BL);
00265 }
00266 
00267 void timer1PWMOff(void)
00268 {
00269     // turn off timer1 PWM mode
00270     cbi(TCCR1A,PWM11);
00271     cbi(TCCR1A,PWM10);
00272     // set PWM1A/B (OutputCompare action) to none
00273     timer1PWMAOff();
00274     timer1PWMBOff();
00275 }
00276 
00277 void timer1PWMAOn(void)
00278 {
00279     // turn on channel A (OC1A) PWM output
00280     // set OC1A as non-inverted PWM
00281     sbi(TCCR1A,COM1A1);
00282     cbi(TCCR1A,COM1A0);
00283 }
00284 
00285 void timer1PWMBOn(void)
00286 {
00287     // turn on channel B (OC1B) PWM output
00288     // set OC1B as non-inverted PWM
00289     sbi(TCCR1A,COM1B1);
00290     cbi(TCCR1A,COM1B0);
00291 }
00292 
00293 void timer1PWMAOff(void)
00294 {
00295     // turn off channel A (OC1A) PWM output
00296     // set OC1A (OutputCompare action) to none
00297     cbi(TCCR1A,COM1A1);
00298     cbi(TCCR1A,COM1A0);
00299 }
00300 
00301 void timer1PWMBOff(void)
00302 {
00303     // turn off channel B (OC1B) PWM output
00304     // set OC1B (OutputCompare action) to none
00305     cbi(TCCR1A,COM1B1);
00306     cbi(TCCR1A,COM1B0);
00307 }
00308 
00309 void timer1PWMASet(u16 pwmDuty)
00310 {
00311     // set PWM (output compare) duty for channel A
00312     // this PWM output is generated on OC1A pin
00313     // NOTE:    pwmDuty should be in the range 0-255 for 8bit PWM
00314     //          pwmDuty should be in the range 0-511 for 9bit PWM
00315     //          pwmDuty should be in the range 0-1023 for 10bit PWM
00316     outp( (pwmDuty>>8), OCR1AH);        // set the high 8bits of OCR1A
00317     outp( (pwmDuty&0x00FF), OCR1AL);    // set the low 8bits of OCR1A
00318 }
00319 
00320 void timer1PWMBSet(u16 pwmDuty)
00321 {
00322     // set PWM (output compare) duty for channel B
00323     // this PWM output is generated on OC1B pin
00324     // NOTE:    pwmDuty should be in the range 0-255 for 8bit PWM
00325     //          pwmDuty should be in the range 0-511 for 9bit PWM
00326     //          pwmDuty should be in the range 0-1023 for 10bit PWM
00327     outp( (pwmDuty>>8), OCR1BH);        // set the high 8bits of OCR1B
00328     outp( (pwmDuty&0x00FF), OCR1BL);    // set the low 8bits of OCR1B
00329 }
00330 
00331 //! Interrupt handler for tcnt0 overflow interrupt
00332 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW0)
00333 {
00334     Timer0Reg0++;           // increment low-order counter
00335 
00336     // increment pause counter
00337     TimerPauseReg++;
00338 
00339     // if a user function is defined, execute it too
00340     if(TimerIntFunc[TIMER0OVERFLOW_INT])
00341         TimerIntFunc[TIMER0OVERFLOW_INT]();
00342 }
00343 
00344 //! Interrupt handler for tcnt1 overflow interrupt
00345 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW1)
00346 {
00347     // if a user function is defined, execute it
00348     if(TimerIntFunc[TIMER1OVERFLOW_INT])
00349         TimerIntFunc[TIMER1OVERFLOW_INT]();
00350 }
00351 
00352 #ifdef TCNT2    // support timer2 only if it exists
00353 //! Interrupt handler for tcnt2 overflow interrupt
00354 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW2)
00355 {
00356     Timer2Reg0++;           // increment low-order counter
00357 
00358     // if a user function is defined, execute it
00359     if(TimerIntFunc[TIMER2OVERFLOW_INT])
00360         TimerIntFunc[TIMER2OVERFLOW_INT]();
00361 }
00362 #endif
00363 
00364 #ifdef OC0
00365 // include support for Output Compare 0 for new AVR processors that support it
00366 //! Interrupt handler for OutputCompare0 match (OC0) interrupt
00367 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE0)
00368 {
00369     // if a user function is defined, execute it
00370     if(TimerIntFunc[TIMER0OUTCOMPARE_INT])
00371         TimerIntFunc[TIMER0OUTCOMPARE_INT]();
00372 }
00373 #endif
00374 
00375 //! Interrupt handler for CutputCompare1A match (OC1A) interrupt
00376 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE1A)
00377 {
00378     // if a user function is defined, execute it
00379     if(TimerIntFunc[TIMER1OUTCOMPAREA_INT])
00380         TimerIntFunc[TIMER1OUTCOMPAREA_INT]();
00381 }
00382 
00383 //! Interrupt handler for OutputCompare1B match (OC1B) interrupt
00384 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE1B)
00385 {
00386     // if a user function is defined, execute it
00387     if(TimerIntFunc[TIMER1OUTCOMPAREB_INT])
00388         TimerIntFunc[TIMER1OUTCOMPAREB_INT]();
00389 }
00390 
00391 //! Interrupt handler for InputCapture1 (IC1) interrupt
00392 TIMER_INTERRUPT_HANDLER(SIG_INPUT_CAPTURE1)
00393 {
00394     // if a user function is defined, execute it
00395     if(TimerIntFunc[TIMER1INPUTCAPTURE_INT])
00396         TimerIntFunc[TIMER1INPUTCAPTURE_INT]();
00397 }
00398 
00399 //! Interrupt handler for OutputCompare2 match (OC2) interrupt
00400 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE2)
00401 {
00402     // if a user function is defined, execute it
00403     if(TimerIntFunc[TIMER2OUTCOMPARE_INT])
00404         TimerIntFunc[TIMER2OUTCOMPARE_INT]();
00405 }

Generated on Sun Feb 22 19:12:31 2004 for Procyon AVRlib by doxygen1.3-rc2