Main Page   Data Structures   File List   Data Fields   Globals  

/timer128.c

Go to the documentation of this file.
00001 /*! \file timer128.c \brief System Timer function library for Mega128. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'timer128.c'
00005 // Title        : System Timer function library for Mega128
00006 // Author       : Pascal Stang - Copyright (C) 2000-2003
00007 // Created      : 11/22/2000
00008 // Revised      : 02/24/2003
00009 // Version      : 1.2
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 #endif
00024 
00025 #include "global.h"
00026 #include "timer128.h"
00027 
00028 // Program ROM constants
00029 // the prescale division values stored in 2^n format
00030 // STOP, CLK, CLK/8, CLK/64, CLK/256, CLK/1024
00031 short __attribute__ ((progmem)) TimerPrescaleFactor[] = {0,0,3,6,8,10};
00032 // the prescale division values stored in 2^n format
00033 // STOP, CLK, CLK/8, CLK/32, CLK/64, CLK/128, CLK/256, CLK/1024
00034 short __attribute__ ((progmem)) TimerRTCPrescaleFactor[] = {0,0,3,5,6,7,8,10};
00035 
00036 // Global variables
00037 // time registers
00038 volatile unsigned long TimerPauseReg;
00039 volatile unsigned long Timer0Reg0;
00040 volatile unsigned long Timer0Reg1;
00041 volatile unsigned long Timer2Reg0;
00042 volatile unsigned long Timer2Reg1;
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     timer2Init();
00072     timer3Init();
00073     // enable interrupts
00074     sei();
00075 }
00076 
00077 void timer0Init()
00078 {
00079     // initialize timer 0
00080     timer0SetPrescaler( TIMER0PRESCALE );   // set prescaler
00081     outp(0, TCNT0);                         // reset TCNT0
00082     sbi(TIMSK, TOIE0);                      // enable TCNT0 overflow interrupt
00083 
00084     timer0ClearOverflowCount();             // initialize time registers
00085 }
00086 
00087 void timer1Init(void)
00088 {
00089     // initialize timer 1
00090     timer1SetPrescaler( TIMER1PRESCALE );   // set prescaler
00091     outp(0, TCNT1H);                        // reset TCNT1
00092     outp(0, TCNT1L);
00093     sbi(TIMSK, TOIE1);                      // enable TCNT1 overflow
00094 }
00095 
00096 void timer2Init(void)
00097 {
00098     // initialize timer 2
00099     timer2SetPrescaler( TIMER2PRESCALE );   // set prescaler
00100     outp(0, TCNT2);                         // reset TCNT2
00101     sbi(TIMSK, TOIE2);                      // enable TCNT2 overflow
00102 
00103     timer2ClearOverflowCount();             // initialize time registers
00104 }
00105 
00106 void timer3Init(void)
00107 {
00108     // initialize timer 3
00109     timer3SetPrescaler( TIMER3PRESCALE );   // set prescaler
00110     outp(0, TCNT3H);                        // reset TCNT3
00111     outp(0, TCNT3L);
00112     sbi(TIMSK, TOIE3);                      // enable TCNT3 overflow
00113 }
00114 
00115 void timer0SetPrescaler(u08 prescale)
00116 {
00117     // set prescaler on timer 0
00118     outp( (inp(TCCR0) & ~TIMER_PRESCALE_MASK) | prescale, TCCR0);
00119 }
00120 
00121 void timer1SetPrescaler(u08 prescale)
00122 {
00123     // set prescaler on timer 1
00124     outp( (inp(TCCR1B) & ~TIMER_PRESCALE_MASK) | prescale, TCCR1B);
00125 }
00126 
00127 void timer2SetPrescaler(u08 prescale)
00128 {
00129     // set prescaler on timer 2
00130     outp( (inp(TCCR2) & ~TIMER_PRESCALE_MASK) | prescale, TCCR2);
00131 }
00132 
00133 void timer3SetPrescaler(u08 prescale)
00134 {
00135     // set prescaler on timer 2
00136     outp( (inp(TCCR3B) & ~TIMER_PRESCALE_MASK) | prescale, TCCR3B);
00137 }
00138 
00139 void timerAttach(u08 interruptNum, void (*userFunc)(void) )
00140 {
00141     // make sure the interrupt number is within bounds
00142     if(interruptNum < TIMER_NUM_INTERRUPTS)
00143     {
00144         // set the interrupt function to run
00145         // the supplied user's function
00146         TimerIntFunc[interruptNum] = userFunc;
00147     }
00148 }
00149 
00150 void timerDetach(u08 interruptNum)
00151 {
00152     // make sure the interrupt number is within bounds
00153     if(interruptNum < TIMER_NUM_INTERRUPTS)
00154     {
00155         // set the interrupt function to run nothing
00156         TimerIntFunc[interruptNum] = 0;
00157     }
00158 }
00159 
00160 void timerPause(unsigned short pause_ms)
00161 {
00162     // pauses for exactly <pause_ms> number of milliseconds
00163     u08 timerThres;
00164     u32 ticRateHz;
00165     u32 pause;
00166 
00167     // capture current pause timer value
00168     timerThres = inb(TCNT2);
00169     // reset pause timer overflow count
00170     TimerPauseReg = 0;
00171     // calculate delay for [pause_ms] milliseconds
00172     // prescaler division = 1<<(PRG_RDB(TimerPrescaleFactor+inp(TCCR2)))
00173     ticRateHz = F_CPU/(1<<(PRG_RDB(TimerPrescaleFactor+inp(TCCR2))));
00174     // precision management
00175     if( ticRateHz > 1000000)
00176         pause = pause_ms*(ticRateHz/1000);
00177     else
00178         pause = (pause_ms*ticRateHz)/1000;
00179     
00180     // loop until time expires
00181     while( ((TimerPauseReg<<8) | inb(TCNT2)) < (pause+timerThres) );
00182 }
00183 
00184 void timer0ClearOverflowCount(void)
00185 {
00186     // clear the timer overflow counter registers
00187     Timer0Reg0 = 0; // initialize time registers
00188     Timer0Reg1 = 0; // initialize time registers
00189 }
00190 
00191 long timer0GetOverflowCount(void)
00192 {
00193     // return the current timer overflow count
00194     // (this is since the last timer0ClearOverflowCount() command was called)
00195     return Timer0Reg0;
00196 }
00197 
00198 void timer2ClearOverflowCount(void)
00199 {
00200     // clear the timer overflow counter registers
00201     Timer2Reg0 = 0; // initialize time registers
00202     Timer2Reg1 = 0; // initialize time registers
00203 }
00204 
00205 long timer2GetOverflowCount(void)
00206 {
00207     // return the current timer overflow count
00208     // (this is since the last timer2ClearOverflowCount() command was called)
00209     return Timer2Reg0;
00210 }
00211 
00212 
00213 void timer1PWMInit(u08 bitRes)
00214 {
00215     // configures timer1 for use with PWM output
00216     // on pins OC1A, OC1B, and OC1C
00217 
00218     // enable Timer1 as 8,9,10bit PWM
00219     if(bitRes == 9)
00220     {   // 9bit mode
00221         sbi(TCCR1A,WGMA1);
00222         cbi(TCCR1A,WGMA0);
00223     }
00224     else if( bitRes == 10 )
00225     {   // 10bit mode
00226         sbi(TCCR1A,WGMA1);
00227         sbi(TCCR1A,WGMA0);
00228     }
00229     else
00230     {   // default 8bit mode
00231         cbi(TCCR1A,WGMA1);
00232         sbi(TCCR1A,WGMA0);
00233     }
00234 
00235     // set clear-timer-on-compare-match
00236     //cbi(TCCR1B,CTC1);
00237     // clear output compare value A
00238     outb(OCR1AH, 0);
00239     outb(OCR1AL, 0);
00240     // clear output compare value B
00241     outb(OCR1BH, 0);
00242     outb(OCR1BL, 0);
00243     // clear output compare value C
00244     outb(OCR1CH, 0);
00245     outb(OCR1CL, 0);
00246 }
00247 
00248 void timer1PWMOff(void)
00249 {
00250     // turn off PWM on Timer1
00251     cbi(TCCR1A,WGMA1);
00252     cbi(TCCR1A,WGMA0);
00253     // clear (disable) clear-timer-on-compare-match
00254     //cbi(TCCR1B,CTC1);
00255     // set PWM1A/B/C (OutputCompare action) to none
00256     timer1PWMAOff();
00257     timer1PWMBOff();
00258     timer1PWMCOff();
00259 }
00260 
00261 void timer1PWMAOn(void)
00262 {
00263     // turn on channel A (OC1A) PWM output
00264     // set OC1A as non-inverted PWM
00265     sbi(TCCR1A,COMA1);
00266     cbi(TCCR1A,COMA0);
00267 }
00268 
00269 void timer1PWMBOn(void)
00270 {
00271     // turn on channel B (OC1B) PWM output
00272     // set OC1B as non-inverted PWM
00273     sbi(TCCR1A,COMB1);
00274     cbi(TCCR1A,COMB0);
00275 }
00276 
00277 void timer1PWMCOn(void)
00278 {
00279     // turn on channel C (OC1C) PWM output
00280     // set OC1C as non-inverted PWM
00281     sbi(TCCR1A,COMC1);
00282     cbi(TCCR1A,COMC0);
00283 }
00284 
00285 void timer1PWMAOff(void)
00286 {
00287     // turn off channel A (OC1A) PWM output
00288     // set OC1A (OutputCompare action) to none
00289     cbi(TCCR1A,COMA1);
00290     cbi(TCCR1A,COMA0);
00291 }
00292 
00293 void timer1PWMBOff(void)
00294 {
00295     // turn off channel B (OC1B) PWM output
00296     // set OC1B (OutputCompare action) to none
00297     cbi(TCCR1A,COMB1);
00298     cbi(TCCR1A,COMB0);
00299 }
00300 
00301 void timer1PWMCOff(void)
00302 {
00303     // turn off channel C (OC1C) PWM output
00304     // set OC1C (OutputCompare action) to none
00305     cbi(TCCR1A,COMC1);
00306     cbi(TCCR1A,COMC0);
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 void timer1PWMCSet(u16 pwmDuty)
00332 {
00333     // set PWM (output compare) duty for channel C
00334     // this PWM output is generated on OC1C pin
00335     // NOTE:    pwmDuty should be in the range 0-255 for 8bit PWM
00336     //          pwmDuty should be in the range 0-511 for 9bit PWM
00337     //          pwmDuty should be in the range 0-1023 for 10bit PWM
00338     outp( (pwmDuty>>8), OCR1CH);        // set the high 8bits of OCR1C
00339     outp( (pwmDuty&0x00FF), OCR1CL);    // set the low 8bits of OCR1C
00340 }
00341 
00342 
00343 void timer3PWMInit(u08 bitRes)
00344 {
00345     // configures timer1 for use with PWM output
00346     // on pins OC3A, OC3B, and OC3C
00347 
00348     // enable Timer3 as 8,9,10bit PWM
00349     if(bitRes == 9)
00350     {   // 9bit mode
00351         sbi(TCCR3A,WGMA1);
00352         cbi(TCCR3A,WGMA0);
00353     }
00354     else if( bitRes == 10 )
00355     {   // 10bit mode
00356         sbi(TCCR3A,WGMA1);
00357         sbi(TCCR3A,WGMA0);
00358     }
00359     else
00360     {   // default 8bit mode
00361         cbi(TCCR3A,WGMA1);
00362         sbi(TCCR3A,WGMA0);
00363     }
00364 
00365     // set clear-timer-on-compare-match
00366     //cbi(TCCR3B,CTC1);
00367     // clear output compare value A
00368     outb(OCR3AH, 0);
00369     outb(OCR3AL, 0);
00370     // clear output compare value B
00371     outb(OCR3BH, 0);
00372     outb(OCR3BL, 0);
00373     // clear output compare value B
00374     outb(OCR3CH, 0);
00375     outb(OCR3CL, 0);
00376 }
00377 
00378 void timer3PWMOff(void)
00379 {
00380     // turn off PWM mode on Timer3
00381     cbi(TCCR3A,WGMA1);
00382     cbi(TCCR3A,WGMA0);
00383     // clear (disable) clear-timer-on-compare-match
00384     //cbi(TCCR3B,CTC1);
00385     // set OC3A/B/C (OutputCompare action) to none
00386     timer3PWMAOff();
00387     timer3PWMBOff();
00388     timer3PWMCOff();
00389 }
00390 
00391 void timer3PWMAOn(void)
00392 {
00393     // turn on channel A (OC3A) PWM output
00394     // set OC3A as non-inverted PWM
00395     sbi(TCCR3A,COMA1);
00396     cbi(TCCR3A,COMA0);
00397 }
00398 
00399 void timer3PWMBOn(void)
00400 {
00401     // turn on channel B (OC3B) PWM output
00402     // set OC3B as non-inverted PWM
00403     sbi(TCCR3A,COMB1);
00404     cbi(TCCR3A,COMB0);
00405 }
00406 
00407 void timer3PWMCOn(void)
00408 {
00409     // turn on channel C (OC3C) PWM output
00410     // set OC3C as non-inverted PWM
00411     sbi(TCCR3A,COMC1);
00412     cbi(TCCR3A,COMC0);
00413 }
00414 
00415 void timer3PWMAOff(void)
00416 {
00417     // turn off channel A (OC3A) PWM output
00418     // set OC3A (OutputCompare action) to none
00419     cbi(TCCR3A,COMA1);
00420     cbi(TCCR3A,COMA0);
00421 }
00422 
00423 void timer3PWMBOff(void)
00424 {
00425     // turn off channel B (OC3B) PWM output
00426     // set OC3B (OutputCompare action) to none
00427     cbi(TCCR3A,COMB1);
00428     cbi(TCCR3A,COMB0);
00429 }
00430 
00431 void timer3PWMCOff(void)
00432 {
00433     // turn off channel C (OC3C) PWM output
00434     // set OC3C (OutputCompare action) to none
00435     cbi(TCCR3A,COMC1);
00436     cbi(TCCR3A,COMC0);
00437 }
00438 
00439 void timer3PWMASet(u16 pwmDuty)
00440 {
00441     // set PWM (output compare) duty for channel A
00442     // this PWM output is generated on OC3A pin
00443     // NOTE:    pwmDuty should be in the range 0-255 for 8bit PWM
00444     //          pwmDuty should be in the range 0-511 for 9bit PWM
00445     //          pwmDuty should be in the range 0-1023 for 10bit PWM
00446     outp( (pwmDuty>>8), OCR3AH);        // set the high 8bits of OCR3A
00447     outp( (pwmDuty&0x00FF), OCR3AL);    // set the low 8bits of OCR3A
00448 }
00449 
00450 void timer3PWMBSet(u16 pwmDuty)
00451 {
00452     // set PWM (output compare) duty for channel B
00453     // this PWM output is generated on OC3B pin
00454     // NOTE:    pwmDuty should be in the range 0-255 for 8bit PWM
00455     //          pwmDuty should be in the range 0-511 for 9bit PWM
00456     //          pwmDuty should be in the range 0-1023 for 10bit PWM
00457     outp( (pwmDuty>>8), OCR3BH);        // set the high 8bits of OCR3B
00458     outp( (pwmDuty&0x00FF), OCR3BL);    // set the low 8bits of OCR3B
00459 }
00460 
00461 void timer3PWMCSet(u16 pwmDuty)
00462 {
00463     // set PWM (output compare) duty for channel B
00464     // this PWM output is generated on OC3C pin
00465     // NOTE:    pwmDuty should be in the range 0-255 for 8bit PWM
00466     //          pwmDuty should be in the range 0-511 for 9bit PWM
00467     //          pwmDuty should be in the range 0-1023 for 10bit PWM
00468     outp( (pwmDuty>>8), OCR3CH);        // set the high 8bits of OCR3C
00469     outp( (pwmDuty&0x00FF), OCR3CL);    // set the low 8bits of OCR3C
00470 }
00471 
00472 
00473 //! Interrupt handler for tcnt0 overflow interrupt
00474 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW0)
00475 {
00476     Timer0Reg0++;       // increment low-order counter
00477     if(!Timer0Reg0)     // if low-order counter rollover
00478         Timer0Reg1++;   // increment high-order counter 
00479 
00480     // if a user function is defined, execute it too
00481     if(TimerIntFunc[TIMER0OVERFLOW_INT])
00482         TimerIntFunc[TIMER0OVERFLOW_INT]();
00483 }
00484 
00485 //! Interrupt handler for Timer1 overflow interrupt
00486 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW1)
00487 {
00488     // if a user function is defined, execute it
00489     if(TimerIntFunc[TIMER1OVERFLOW_INT])
00490         TimerIntFunc[TIMER1OVERFLOW_INT]();
00491 }
00492 
00493 //! Interrupt handler for Timer2 overflow interrupt
00494 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW2)
00495 {
00496     Timer2Reg0++;       // increment low-order counter
00497     if(!Timer2Reg0)     // if low-order counter rollover
00498         Timer2Reg1++;   // increment high-order counter 
00499 
00500     // increment pause counter
00501     TimerPauseReg++;
00502 
00503     // if a user function is defined, execute it
00504     if(TimerIntFunc[TIMER2OVERFLOW_INT])
00505         TimerIntFunc[TIMER2OVERFLOW_INT]();
00506 }
00507 
00508 //! Interrupt handler for Timer3 overflow interrupt
00509 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW3)
00510 {
00511     // if a user function is defined, execute it
00512     if(TimerIntFunc[TIMER3OVERFLOW_INT])
00513         TimerIntFunc[TIMER3OVERFLOW_INT]();
00514 }
00515 
00516 //! Interrupt handler for OutputCompare0 match (OC0) interrupt
00517 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE0)
00518 {
00519     // if a user function is defined, execute it
00520     if(TimerIntFunc[TIMER0OUTCOMPARE_INT])
00521         TimerIntFunc[TIMER0OUTCOMPARE_INT]();
00522 }
00523 
00524 //! Interrupt handler for OutputCompare1A match (OC1A) interrupt
00525 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE1A)
00526 {
00527     // if a user function is defined, execute it
00528     if(TimerIntFunc[TIMER1OUTCOMPAREA_INT])
00529         TimerIntFunc[TIMER1OUTCOMPAREA_INT]();
00530 }
00531 
00532 //! Interrupt handler for OutputCompare1B match (OC1B) interrupt
00533 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE1B)
00534 {
00535     // if a user function is defined, execute it
00536     if(TimerIntFunc[TIMER1OUTCOMPAREB_INT])
00537         TimerIntFunc[TIMER1OUTCOMPAREB_INT]();
00538 }
00539 
00540 //! Interrupt handler for OutputCompare1C match (OC1C) interrupt
00541 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE1C)
00542 {
00543     // if a user function is defined, execute it
00544     if(TimerIntFunc[TIMER1OUTCOMPAREC_INT])
00545         TimerIntFunc[TIMER1OUTCOMPAREC_INT]();
00546 }
00547 
00548 //! Interrupt handler for InputCapture1(IC1) interrupt
00549 TIMER_INTERRUPT_HANDLER(SIG_INPUT_CAPTURE1)
00550 {
00551     // if a user function is defined, execute it
00552     if(TimerIntFunc[TIMER1INPUTCAPTURE_INT])
00553         TimerIntFunc[TIMER1INPUTCAPTURE_INT]();
00554 }
00555 
00556 //! Interrupt handler for OutputCompare2 match (OC2) interrupt
00557 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE2)
00558 {
00559     // if a user function is defined, execute it
00560     if(TimerIntFunc[TIMER2OUTCOMPARE_INT])
00561         TimerIntFunc[TIMER2OUTCOMPARE_INT]();
00562 }
00563 
00564 //! Interrupt handler for OutputCompare3A match (OC3A) interrupt
00565 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE3A)
00566 {
00567     // if a user function is defined, execute it
00568     if(TimerIntFunc[TIMER3OUTCOMPAREA_INT])
00569         TimerIntFunc[TIMER3OUTCOMPAREA_INT]();
00570 }
00571 
00572 //! Interrupt handler for OutputCompare3B match (OC3B) interrupt
00573 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE3B)
00574 {
00575     // if a user function is defined, execute it
00576     if(TimerIntFunc[TIMER1OUTCOMPAREB_INT])
00577         TimerIntFunc[TIMER1OUTCOMPAREB_INT]();
00578 }
00579 
00580 //! Interrupt handler for OutputCompare3C match (OC3C) interrupt
00581 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE3C)
00582 {
00583     // if a user function is defined, execute it
00584     if(TimerIntFunc[TIMER3OUTCOMPAREC_INT])
00585         TimerIntFunc[TIMER3OUTCOMPAREC_INT]();
00586 }
00587 
00588 //! Interrupt handler for InputCapture3 (IC3) interrupt
00589 TIMER_INTERRUPT_HANDLER(SIG_INPUT_CAPTURE3)
00590 {
00591     // if a user function is defined, execute it
00592     if(TimerIntFunc[TIMER3INPUTCAPTURE_INT])
00593         TimerIntFunc[TIMER3INPUTCAPTURE_INT]();
00594 }

Generated on Fri Aug 1 10:42:42 2003 for Procyon AVRlib by doxygen1.2.18