?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 6

Line No. Rev Author Line
1 6 kaklik /*! \file timerx8.c \brief Timer function library for ATmegaXX8 Processors. */
2 //*****************************************************************************
3 //
4 // File Name : 'timerx8.c'
5 // Title : Timer function library for ATmegaXX8 Processors
6 // Author : Pascal Stang - Copyright (C) 2000-2005
7 // Created : 11/22/2000
8 // Revised : 06/15/2005
9 // Version : 1.0
10 // Target MCU : Atmel AVR Series
11 // Editor Tabs : 4
12 //
13 // This code is distributed under the GNU Public License
14 // which can be found at http://www.gnu.org/licenses/gpl.txt
15 //
16 //*****************************************************************************
17  
18 #include <avr/io.h>
19 #include <avr/interrupt.h>
20 #include <avr/pgmspace.h>
21 #include <avr/sleep.h>
22  
23 #include "global.h"
24 #include "timerx8.h"
25  
26 // Program ROM constants
27 // the prescale division values stored in order of timer control register index
28 // STOP, CLK, CLK/8, CLK/64, CLK/256, CLK/1024
29 unsigned short __attribute__ ((progmem)) TimerPrescaleFactor[] = {0,1,8,64,256,1024};
30 // the prescale division values stored in order of timer control register index
31 // STOP, CLK, CLK/8, CLK/32, CLK/64, CLK/128, CLK/256, CLK/1024
32 unsigned short __attribute__ ((progmem)) TimerRTCPrescaleFactor[] = {0,1,8,32,64,128,256,1024};
33  
34 // Global variables
35 // time registers
36 volatile unsigned long TimerPauseReg;
37 volatile unsigned long Timer0Reg0;
38 volatile unsigned long Timer2Reg0;
39  
40 typedef void (*voidFuncPtr)(void);
41 volatile static voidFuncPtr TimerIntFunc[TIMER_NUM_INTERRUPTS];
42  
43 // delay for a minimum of <us> microseconds
44 // the time resolution is dependent on the time the loop takes
45 // e.g. with 4Mhz and 5 cycles per loop, the resolution is 1.25 us
46 void delay_us(unsigned short time_us)
47 {
48 unsigned short delay_loops;
49 register unsigned short i;
50  
51 delay_loops = (time_us+3)/5*CYCLES_PER_US; // +3 for rounding up (dirty)
52  
53 // one loop takes 5 cpu cycles
54 for (i=0; i < delay_loops; i++) {};
55 }
56 /*
57 void delay_ms(unsigned char time_ms)
58 {
59 unsigned short delay_count = F_CPU / 4000;
60  
61 unsigned short cnt;
62 asm volatile ("\n"
63 "L_dl1%=:\n\t"
64 "mov %A0, %A2\n\t"
65 "mov %B0, %B2\n"
66 "L_dl2%=:\n\t"
67 "sbiw %A0, 1\n\t"
68 "brne L_dl2%=\n\t"
69 "dec %1\n\t" "brne L_dl1%=\n\t":"=&w" (cnt)
70 :"r"(time_ms), "r"((unsigned short) (delay_count))
71 );
72 }
73 */
74 void timerInit(void)
75 {
76 u08 intNum;
77 // detach all user functions from interrupts
78 for(intNum=0; intNum<TIMER_NUM_INTERRUPTS; intNum++)
79 timerDetach(intNum);
80  
81 // initialize all timers
82 timer0Init();
83 timer1Init();
84 #ifdef TCNT2 // support timer2 only if it exists
85 timer2Init();
86 #endif
87 // enable interrupts
88 sei();
89 }
90  
91 void timer0Init()
92 {
93 // initialize timer 0
94 timer0SetPrescaler( TIMER0PRESCALE ); // set prescaler
95 TCNT0 = 0; // reset TCNT0
96 sbi(TIMSK0, TOIE0); // enable TCNT0 overflow interrupt
97  
98 timer0ClearOverflowCount(); // initialize time registers
99 }
100  
101 void timer1Init(void)
102 {
103 // initialize timer 1
104 timer1SetPrescaler( TIMER1PRESCALE ); // set prescaler
105 TCNT1 = 0; // reset TCNT1
106 sbi(TIMSK1, TOIE1); // enable TCNT1 overflow
107 }
108  
109 #ifdef TCNT2 // support timer2 only if it exists
110 void timer2Init(void)
111 {
112 // initialize timer 2
113 timer2SetPrescaler( TIMER2PRESCALE ); // set prescaler
114 TCNT2 = 0; // reset TCNT2
115 sbi(TIMSK2, TOIE2); // enable TCNT2 overflow
116  
117 timer2ClearOverflowCount(); // initialize time registers
118 }
119 #endif
120  
121 void timer0SetPrescaler(u08 prescale)
122 {
123 // set prescaler on timer 0
124 TCCR0B = ((TCCR0B & ~TIMER_PRESCALE_MASK) | prescale);
125 }
126  
127 void timer1SetPrescaler(u08 prescale)
128 {
129 // set prescaler on timer 1
130 TCCR1B = ((TCCR1B & ~TIMER_PRESCALE_MASK) | prescale);
131 }
132  
133 #ifdef TCNT2 // support timer2 only if it exists
134 void timer2SetPrescaler(u08 prescale)
135 {
136 // set prescaler on timer 2
137 TCCR2B = ((TCCR2B & ~TIMER_PRESCALE_MASK) | prescale);
138 }
139 #endif
140  
141 u16 timer0GetPrescaler(void)
142 {
143 // get the current prescaler setting
144 return (pgm_read_word(TimerPrescaleFactor+(TCCR0B & TIMER_PRESCALE_MASK)));
145 }
146  
147 u16 timer1GetPrescaler(void)
148 {
149 // get the current prescaler setting
150 return (pgm_read_word(TimerPrescaleFactor+(TCCR1B & TIMER_PRESCALE_MASK)));
151 }
152  
153 #ifdef TCNT2 // support timer2 only if it exists
154 u16 timer2GetPrescaler(void)
155 {
156 //TODO: can we assume for all 3-timer AVR processors,
157 // that timer2 is the RTC timer?
158  
159 // get the current prescaler setting
160 return (pgm_read_word(TimerRTCPrescaleFactor+(TCCR2B & TIMER_PRESCALE_MASK)));
161 }
162 #endif
163  
164 void timerAttach(u08 interruptNum, void (*userFunc)(void) )
165 {
166 // make sure the interrupt number is within bounds
167 if(interruptNum < TIMER_NUM_INTERRUPTS)
168 {
169 // set the interrupt function to run
170 // the supplied user's function
171 TimerIntFunc[interruptNum] = userFunc;
172 }
173 }
174  
175 void timerDetach(u08 interruptNum)
176 {
177 // make sure the interrupt number is within bounds
178 if(interruptNum < TIMER_NUM_INTERRUPTS)
179 {
180 // set the interrupt function to run nothing
181 TimerIntFunc[interruptNum] = 0;
182 }
183 }
184 /*
185 u32 timerMsToTics(u16 ms)
186 {
187 // calculate the prescaler division rate
188 u16 prescaleDiv = 1<<(pgm_read_byte(TimerPrescaleFactor+inb(TCCR0)));
189 // calculate the number of timer tics in x milliseconds
190 return (ms*(F_CPU/(prescaleDiv*256)))/1000;
191 }
192  
193 u16 timerTicsToMs(u32 tics)
194 {
195 // calculate the prescaler division rate
196 u16 prescaleDiv = 1<<(pgm_read_byte(TimerPrescaleFactor+inb(TCCR0)));
197 // calculate the number of milliseconds in x timer tics
198 return (tics*1000*(prescaleDiv*256))/F_CPU;
199 }
200 */
201 void timerPause(unsigned short pause_ms)
202 {
203 // pauses for exactly <pause_ms> number of milliseconds
204 u08 timerThres;
205 u32 ticRateHz;
206 u32 pause;
207  
208 // capture current pause timer value
209 timerThres = TCNT0;
210 // reset pause timer overflow count
211 TimerPauseReg = 0;
212 // calculate delay for [pause_ms] milliseconds
213 // prescaler division = 1<<(pgm_read_byte(TimerPrescaleFactor+inb(TCCR0)))
214 ticRateHz = F_CPU/timer0GetPrescaler();
215 // precision management
216 // prevent overflow and precision underflow
217 // -could add more conditions to improve accuracy
218 if( ((ticRateHz < 429497) && (pause_ms <= 10000)) )
219 pause = (pause_ms*ticRateHz)/1000;
220 else
221 pause = pause_ms*(ticRateHz/1000);
222  
223 // loop until time expires
224 while( ((TimerPauseReg<<8) | (TCNT0)) < (pause+timerThres) )
225 {
226 if( TimerPauseReg < (pause>>8));
227 {
228 // save power by idling the processor
229 set_sleep_mode(SLEEP_MODE_IDLE);
230 sleep_mode();
231 }
232 }
233  
234 /* old inaccurate code, for reference
235  
236 // calculate delay for [pause_ms] milliseconds
237 u16 prescaleDiv = 1<<(pgm_read_byte(TimerPrescaleFactor+inb(TCCR0)));
238 u32 pause = (pause_ms*(F_CPU/(prescaleDiv*256)))/1000;
239  
240 TimerPauseReg = 0;
241 while(TimerPauseReg < pause);
242  
243 */
244 }
245  
246 void timer0ClearOverflowCount(void)
247 {
248 // clear the timer overflow counter registers
249 Timer0Reg0 = 0; // initialize time registers
250 }
251  
252 long timer0GetOverflowCount(void)
253 {
254 // return the current timer overflow count
255 // (this is since the last timer0ClearOverflowCount() command was called)
256 return Timer0Reg0;
257 }
258  
259 #ifdef TCNT2 // support timer2 only if it exists
260 void timer2ClearOverflowCount(void)
261 {
262 // clear the timer overflow counter registers
263 Timer2Reg0 = 0; // initialize time registers
264 }
265  
266 long timer2GetOverflowCount(void)
267 {
268 // return the current timer overflow count
269 // (this is since the last timer2ClearOverflowCount() command was called)
270 return Timer2Reg0;
271 }
272 #endif
273  
274 void timer1PWMInit(u08 bitRes)
275 {
276 // configures timer1 for use with PWM output
277 // on OC1A and OC1B pins
278  
279 // enable timer1 as 8,9,10bit PWM
280 if(bitRes == 9)
281 { // 9bit mode
282 sbi(TCCR1A,PWM11);
283 cbi(TCCR1A,PWM10);
284 }
285 else if( bitRes == 10 )
286 { // 10bit mode
287 sbi(TCCR1A,PWM11);
288 sbi(TCCR1A,PWM10);
289 }
290 else
291 { // default 8bit mode
292 cbi(TCCR1A,PWM11);
293 sbi(TCCR1A,PWM10);
294 }
295  
296 // clear output compare value A
297 OCR1A = 0;
298 // clear output compare value B
299 OCR1B = 0;
300 }
301  
302 #ifdef WGM10
303 // include support for arbitrary top-count PWM
304 // on new AVR processors that support it
305 void timer1PWMInitICR(u16 topcount)
306 {
307 // set PWM mode with ICR top-count
308 cbi(TCCR1A,WGM10);
309 sbi(TCCR1A,WGM11);
310 sbi(TCCR1B,WGM12);
311 sbi(TCCR1B,WGM13);
312  
313 // set top count value
314 ICR1 = topcount;
315  
316 // clear output compare value A
317 OCR1A = 0;
318 // clear output compare value B
319 OCR1B = 0;
320  
321 }
322 #endif
323  
324 void timer1PWMOff(void)
325 {
326 // turn off timer1 PWM mode
327 cbi(TCCR1A,PWM11);
328 cbi(TCCR1A,PWM10);
329 // set PWM1A/B (OutputCompare action) to none
330 timer1PWMAOff();
331 timer1PWMBOff();
332 }
333  
334 void timer1PWMAOn(void)
335 {
336 // turn on channel A (OC1A) PWM output
337 // set OC1A as non-inverted PWM
338 sbi(TCCR1A,COM1A1);
339 cbi(TCCR1A,COM1A0);
340 }
341  
342 void timer1PWMBOn(void)
343 {
344 // turn on channel B (OC1B) PWM output
345 // set OC1B as non-inverted PWM
346 sbi(TCCR1A,COM1B1);
347 cbi(TCCR1A,COM1B0);
348 }
349  
350 void timer1PWMAOff(void)
351 {
352 // turn off channel A (OC1A) PWM output
353 // set OC1A (OutputCompare action) to none
354 cbi(TCCR1A,COM1A1);
355 cbi(TCCR1A,COM1A0);
356 }
357  
358 void timer1PWMBOff(void)
359 {
360 // turn off channel B (OC1B) PWM output
361 // set OC1B (OutputCompare action) to none
362 cbi(TCCR1A,COM1B1);
363 cbi(TCCR1A,COM1B0);
364 }
365  
366 void timer1PWMASet(u16 pwmDuty)
367 {
368 // set PWM (output compare) duty for channel A
369 // this PWM output is generated on OC1A pin
370 // NOTE: pwmDuty should be in the range 0-255 for 8bit PWM
371 // pwmDuty should be in the range 0-511 for 9bit PWM
372 // pwmDuty should be in the range 0-1023 for 10bit PWM
373 //outp( (pwmDuty>>8), OCR1AH); // set the high 8bits of OCR1A
374 //outp( (pwmDuty&0x00FF), OCR1AL); // set the low 8bits of OCR1A
375 OCR1A = pwmDuty;
376 }
377  
378 void timer1PWMBSet(u16 pwmDuty)
379 {
380 // set PWM (output compare) duty for channel B
381 // this PWM output is generated on OC1B pin
382 // NOTE: pwmDuty should be in the range 0-255 for 8bit PWM
383 // pwmDuty should be in the range 0-511 for 9bit PWM
384 // pwmDuty should be in the range 0-1023 for 10bit PWM
385 //outp( (pwmDuty>>8), OCR1BH); // set the high 8bits of OCR1B
386 //outp( (pwmDuty&0x00FF), OCR1BL); // set the low 8bits of OCR1B
387 OCR1B = pwmDuty;
388 }
389  
390 //! Interrupt handler for tcnt0 overflow interrupt
391 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW0)
392 {
393 Timer0Reg0++; // increment low-order counter
394  
395 // increment pause counter
396 TimerPauseReg++;
397  
398 // if a user function is defined, execute it too
399 if(TimerIntFunc[TIMER0OVERFLOW_INT])
400 TimerIntFunc[TIMER0OVERFLOW_INT]();
401 }
402  
403 //! Interrupt handler for tcnt1 overflow interrupt
404 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW1)
405 {
406 // if a user function is defined, execute it
407 if(TimerIntFunc[TIMER1OVERFLOW_INT])
408 TimerIntFunc[TIMER1OVERFLOW_INT]();
409 }
410  
411 #ifdef TCNT2 // support timer2 only if it exists
412 //! Interrupt handler for tcnt2 overflow interrupt
413 TIMER_INTERRUPT_HANDLER(SIG_OVERFLOW2)
414 {
415 Timer2Reg0++; // increment low-order counter
416  
417 // if a user function is defined, execute it
418 if(TimerIntFunc[TIMER2OVERFLOW_INT])
419 TimerIntFunc[TIMER2OVERFLOW_INT]();
420 }
421 #endif
422  
423 #ifdef OCR0
424 // include support for Output Compare 0 for new AVR processors that support it
425 //! Interrupt handler for OutputCompare0 match (OC0) interrupt
426 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE0)
427 {
428 // if a user function is defined, execute it
429 if(TimerIntFunc[TIMER0OUTCOMPARE_INT])
430 TimerIntFunc[TIMER0OUTCOMPARE_INT]();
431 }
432 #endif
433  
434 //! Interrupt handler for CutputCompare1A match (OC1A) interrupt
435 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE1A)
436 {
437 // if a user function is defined, execute it
438 if(TimerIntFunc[TIMER1OUTCOMPAREA_INT])
439 TimerIntFunc[TIMER1OUTCOMPAREA_INT]();
440 }
441  
442 //! Interrupt handler for OutputCompare1B match (OC1B) interrupt
443 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE1B)
444 {
445 // if a user function is defined, execute it
446 if(TimerIntFunc[TIMER1OUTCOMPAREB_INT])
447 TimerIntFunc[TIMER1OUTCOMPAREB_INT]();
448 }
449  
450 //! Interrupt handler for InputCapture1 (IC1) interrupt
451 TIMER_INTERRUPT_HANDLER(SIG_INPUT_CAPTURE1)
452 {
453 // if a user function is defined, execute it
454 if(TimerIntFunc[TIMER1INPUTCAPTURE_INT])
455 TimerIntFunc[TIMER1INPUTCAPTURE_INT]();
456 }
457  
458 //! Interrupt handler for OutputCompare2A match (OC2A) interrupt
459 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE2A)
460 {
461 // if a user function is defined, execute it
462 if(TimerIntFunc[TIMER2OUTCOMPARE_INT])
463 TimerIntFunc[TIMER2OUTCOMPARE_INT]();
464 }
465  
466 //! Interrupt handler for OutputCompare2B match (OC2B) interrupt
467 TIMER_INTERRUPT_HANDLER(SIG_OUTPUT_COMPARE2B)
468 {
469 // if a user function is defined, execute it
470 if(TimerIntFunc[TIMER2OUTCOMPARE_INT])
471 TimerIntFunc[TIMER2OUTCOMPARE_INT]();
472 }
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3