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