296215db3625001841ae395bf1a0a1f370d798c8
[bertos.git] / drv / timer_avr.h
1 /*!
2  * \file
3  * <!--
4  * Copyright 2003,2004 Develer S.r.l. (http://www.develer.com/)
5  * Copyright 2000 Bernardo Innocenti <bernie@develer.com>
6  * This file is part of DevLib - See devlib/README for information.
7  * -->
8  *
9  * \version $Id$
10  *
11  * \author Bernardo Innocenti <bernie@develer.com>
12  *
13  * \brief Low-level timer module for AVR
14  */
15
16 /*
17  * $Log$
18  * Revision 1.2  2004/06/03 11:27:09  bernie
19  * Add dual-license information.
20  *
21  * Revision 1.1  2004/05/23 18:23:30  bernie
22  * Import drv/timer module.
23  *
24  */
25
26 #ifndef DRV_TIMER_AVR_H
27 #define DRV_TIMER_AVR_H
28
29 #include <avr/wdt.h>
30
31 #       define TIMER_RETRIGGER /* Not needed, timer retriggers automatically  */
32
33         /*!
34          * System timer: additional division after the prescaler
35          * 12288000 / 64 / 192 (0..191) = 1 ms
36          */
37 #       define OCR_DIVISOR 191
38
39         /*! HW dependent timer initialization  */
40 #if defined(CONFIG_TIMER_ON_TIMER0)
41
42 #               define TIMER_INIT \
43                 do { \
44                         DISABLE_INTS; \
45                         \
46                         /* Reset Timer flags */ \
47                         TIFR = BV(OCF0) | BV(TOV0); \
48                         \
49                         /* Setup Timer/Counter interrupt */ \
50                         ASSR = 0x00;                  /* internal system clock */ \
51                         TCCR0 = BV(WGM01) | BV(CS02); /* Clear on Compare match & prescaler = 64 */ \
52                         TCNT0 = 0x00;                 /* initialization of Timer/Counter */ \
53                         OCR0 = OCR_DIVISOR;           /* Timer/Counter Output Compare Register */ \
54                         \
55                         /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */ \
56                         TIMSK &= ~BV(TOIE0); \
57                         TIMSK |= BV(OCIE0); \
58                         \
59                         ENABLE_INTS; \
60                 } while (0)
61
62 #elif defined(CONFIG_TIMER_ON_TIMER1_OVERFLOW)
63
64 #               define TIMER_INIT \
65                 do { \
66                         DISABLE_INTS; \
67                         \
68                         /* Reset Timer overflow flag */ \
69                         TIFR |= BV(TOV1); \
70                         \
71                         /* Fast PWM mode, 24 kHz, no prescaling */ \
72                         TCCR1A |= BV(WGM11); \
73                         TCCR1A &= ~BV(WGM10); \
74                         TCCR1B |= BV(WGM12) | BV(CS10); \
75                         TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12)); \
76                         \
77                         TCNT1 = 0x00;         /* initialization of Timer/Counter */ \
78                         \
79                         /* Enable timer interrupt: Timer/Counter1 Overflow */ \
80                         TIMSK |= BV(TOIE1); \
81                         \
82                         ENABLE_INTS; \
83                 } while (0)
84
85 #elif defined(CONFIG_TIMER_ON_TIMER2)
86
87 #               define TIMER_INIT \
88                 do { \
89                         DISABLE_INTS; \
90                         \
91                         /* Reset Timer flags */ \
92                         TIFR = BV(OCF2) | BV(TOV2); \
93                         \
94                         /* Setup Timer/Counter interrupt */ \
95                         TCCR2 = BV(WGM21) | BV(CS21) | BV(CS20); \
96                                               /* Clear on Compare match & prescaler = 64, internal sys clock */ \
97                         TCNT2 = 0x00;         /* initialization of Timer/Counter */ \
98                         OCR2 = OCR_DIVISOR;   /* Timer/Counter Output Compare Register */ \
99                         \
100                         /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */ \
101                         TIMSK &= ~BV(TOIE2); \
102                         TIMSK |= BV(OCIE2); \
103                         \
104                         ENABLE_INTS; \
105                 } while (0)
106
107 #else
108 #               error Choose witch timer to use with CONFIG_TIMER_ON_TIMERx
109 #endif /* CONFIG_TIMER_ON_TIMERx */
110
111
112 #if defined(CONFIG_TIMER_ON_TIMER1_OVERFLOW)
113
114         #define DEFINE_TIMER_ISR        \
115                 static void timer_handler(void)
116
117         /*
118         * Timer 1 overflow irq handler.
119         */
120         SIGNAL(SIG_OVERFLOW1)
121         {
122                 /*!
123                 * How many overflow we have to count before calling the true timer handler.
124                 * If timer overflow is at 24 kHz, with a value of 24 we have 1 ms between
125                 * each call.
126                 */
127         #define TIMER1_OVF_COUNT 24
128
129                 static uint8_t count = TIMER1_OVF_COUNT;
130
131                 count--;
132                 if (!count)
133                 {
134                         timer_handler();
135                         count = TIMER1_OVF_COUNT;
136                 }
137         }
138
139 #elif defined (CONFIG_TIMER_ON_TIMER0)
140
141         #define DEFINE_TIMER_ISR        \
142                 SIGNAL(SIG_OUTPUT_COMPARE0)
143
144 #elif defined(CONFIG_TIMER_ON_TIMER2)
145
146         #define DEFINE_TIMER_ISR        \
147                 SIGNAL(SIG_OUTPUT_COMPARE2)
148
149 #else
150 #       error Choose witch timer to use with CONFIG_TIMER_ON_TIMERx
151 #endif /* CONFIG_TIMER_ON_TIMERx */
152
153 #endif /* DRV_TIMER_AVR_H */