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