Refactor to decouple timer ticks from milliseconds.
[bertos.git] / drv / timer_avr.c
1 /*!
2  * \file
3  * <!--
4  * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
5  * This file is part of DevLib - See README.devlib for information.
6  * -->
7  *
8  * \version $Id$
9  *
10  * \author Bernardo Innocenti <bernie@develer.com>
11  * \author Francesco Sacchi <batt@develer.com>
12  *
13  * \brief Low-level timer module for AVR (implementation).
14  */
15
16 /*#*
17  *#* $Log$
18  *#* Revision 1.1  2005/07/19 07:28:36  bernie
19  *#* Refactor to decouple timer ticks from milliseconds.
20  *#*
21  *#* Revision 1.1  2005/05/24 09:17:58  batt
22  *#* Move drivers to top-level.
23  *#*
24  *#*/
25 #include <drv/timer_avr.h>
26 #include <arch_config.h> // ARCH_BOARD_KC
27 #include <cfg/macros.h> // BV()
28 #include <hw.h>
29
30 #include <avr/signal.h>
31 #include <avr/io.h>
32
33 /*! HW dependent timer initialization  */
34 #if (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE0)
35
36         static void timer_hw_init(void)
37         {
38                 cpuflags_t flags;
39                 IRQ_SAVE_DISABLE(flags);
40
41                 /* Reset Timer flags */
42                 TIFR = BV(OCF0) | BV(TOV0);
43
44                 /* Setup Timer/Counter interrupt */
45                 ASSR = 0x00;                  /* Internal system clock */
46                 TCCR0 = BV(WGM01)             /* Clear on Compare match */
47                         #if TIMER_PRESCALER == 64
48                                 | BV(CS02)
49                         #else
50                                 #error Unsupported value of TIMER_PRESCALER
51                         #endif
52                 ;
53                 TCNT0 = 0x00;                 /* Initialization of Timer/Counter */
54                 OCR0 = OCR_DIVISOR;           /* Timer/Counter Output Compare Register */
55
56                 /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
57                 TIMSK &= ~BV(TOIE0);
58                 TIMSK |= BV(OCIE0);
59
60                 IRQ_RESTORE(flags);
61         }
62
63         INLINE hptime_t timer_hw_hpread(void)
64         {
65                 return TCNT0;
66         }
67
68 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW1)
69
70         static void timer_hw_init(void)
71         {
72                 cpuflags_t flags;
73                 IRQ_SAVE_DISABLE(flags);
74
75                 /* Reset Timer overflow flag */
76                 TIFR |= BV(TOV1);
77
78                 /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
79                 #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
80                         TCCR1A |= BV(WGM11);
81                         TCCR1A &= ~BV(WGM10);
82                         TCCR1B |= BV(WGM12) | BV(CS10);
83                         TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12));
84                 /* Fast PWM mode, 8 bit, 24 kHz, no prescaling. */
85                 #elif (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 8)
86                         TCCR1A |= BV(WGM10);
87                         TCCR1A &= ~BV(WGM11);
88                         TCCR1B |= BV(WGM12) | BV(CS10);
89                         TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12));
90                 #else
91                         #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
92                 #endif
93
94                 TCNT1 = 0x00;         /* initialization of Timer/Counter */
95
96                 /* Enable timer interrupt: Timer/Counter1 Overflow */
97                 TIMSK |= BV(TOIE1);
98
99                 IRQ_RESTORE(flags);
100         }
101
102         INLINE hptime_t timer_hw_hpread(void)
103         {
104                 return TCNT1;
105         }
106
107 #elif (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE2)
108
109         static void timer_hw_init(void)
110         {
111                 cpuflags_t flags;
112                 IRQ_SAVE_DISABLE(flags);
113
114                 /* Reset Timer flags */
115                 TIFR = BV(OCF2) | BV(TOV2);
116
117                 /* Setup Timer/Counter interrupt */
118                 TCCR2 = BV(WGM21)
119                         #if TIMER_PRESCALER == 64
120                                 | BV(CS21) | BV(CS20)
121                         #else
122                                 #error Unsupported value of TIMER_PRESCALER
123                         #endif
124                 ;
125                 /* Clear on Compare match & prescaler = 64, internal sys clock.
126                    When changing prescaler change TIMER_HW_HPTICKS_PER_SEC too */
127                 TCNT2 = 0x00;         /* initialization of Timer/Counter */
128                 OCR2 = OCR_DIVISOR;   /* Timer/Counter Output Compare Register */
129
130                 /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
131                 TIMSK &= ~BV(TOIE2);
132                 TIMSK |= BV(OCIE2);
133
134                 IRQ_RESTORE(flags);
135         }
136
137         INLINE hptime_t timer_hw_hpread(void)
138         {
139                 return TCNT2;
140         }
141 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW3)
142
143         static void timer_hw_init(void)
144         {
145                 cpuflags_t flags;
146                 IRQ_SAVE_DISABLE(flags);
147
148                 /* Reset Timer overflow flag */
149                 TIFR |= BV(TOV3);
150
151                 /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
152                 #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
153                         TCCR3A |= BV(WGM31);
154                         TCCR3A &= ~BV(WGM30);
155                         TCCR3B |= BV(WGM32) | BV(CS30);
156                         TCCR3B &= ~(BV(WGM33) | BV(CS31) | BV(CS32));
157                 /* Fast PWM mode, 8 bit, 24 kHz, no prescaling. */
158                 #elif (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 8)
159                         TCCR3A |= BV(WGM30);
160                         TCCR3A &= ~BV(WGM31);
161                         TCCR3B |= BV(WGM32) | BV(CS30);
162                         TCCR3B &= ~(BV(WGM33) | BV(CS31) | BV(CS32));
163                 #else
164                         #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
165                 #endif
166
167                 TCNT3 = 0x00;         /* initialization of Timer/Counter */
168
169                 /* Enable timer interrupt: Timer/Counter3 Overflow */
170                 /* ATTENTION! TOIE3 is only on ETIMSK, not TIMSK */
171                 ETIMSK |= BV(TOIE3);
172
173                 IRQ_RESTORE(flags);
174         }
175
176         INLINE hptime_t timer_hw_hpread(void)
177         {
178                 return TCNT3;
179         }
180
181 #else
182         #error Unimplemented value for CONFIG_TIMER
183 #endif /* CONFIG_TIMER */
184