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