Sistema l'errore da me commesso in fase di conversione...
[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.6  2007/06/07 14:35:12  batt
19  *#* Merge from project_ks.
20  *#*
21  *#* Revision 1.5  2007/03/21 11:03:56  batt
22  *#* Add missing support for ATMega1281.
23  *#*
24  *#* Revision 1.4  2006/07/19 12:56:26  bernie
25  *#* Convert to new Doxygen style.
26  *#*
27  *#* Revision 1.3  2006/06/12 21:37:02  marco
28  *#* implemented some commands (ver and sleep)
29  *#*
30  *#* Revision 1.2  2006/05/18 00:37:58  bernie
31  *#* Don't include unneeded header hw.h.
32  *#*
33  *#* Revision 1.1  2005/07/19 07:28:36  bernie
34  *#* Refactor to decouple timer ticks from milliseconds.
35  *#*
36  *#* Revision 1.1  2005/05/24 09:17:58  batt
37  *#* Move drivers to top-level.
38  *#*
39  *#*/
40 #include <drv/timer_avr.h>
41 #include <cfg/macros.h> // BV()
42
43 #include <cfg/cpu.h>
44
45 #include <avr/interrupt.h>
46 #include <avr/io.h>
47
48 #if CPU_AVR_ATMEGA1281 || CPU_AVR_ATMEGA168
49         #define REG_TIFR0 TIFR0
50         #define REG_TIFR2 TIFR2
51
52         #define REG_TIMSK0 TIMSK0
53         #define REG_TIMSK2 TIMSK2
54
55         #define REG_TCCR2A TCCR2A
56         #define REG_TCCR2B TCCR2B
57
58         #define REG_OCR2A  OCR2A
59
60         #define BIT_OCF0A  OCF0A
61         #define BIT_OCF2A  OCF2A
62
63         #define BIT_OCIE0A OCIE0A
64         #define BIT_OCIE2A OCIE2A
65 #else
66         #define REG_TIFR0 TIFR
67         #define REG_TIFR2 TIFR
68
69         #define REG_TIMSK0 TIMSK
70         #define REG_TIMSK2 TIMSK
71
72         #define REG_TCCR2A TCCR2
73         #define REG_TCCR2B TCCR2
74
75         #define REG_OCR2A  OCR2
76
77         #define BIT_OCF0A  OCF0
78         #define BIT_OCF2A  OCF2
79
80         #define BIT_OCIE0A OCIE0
81         #define BIT_OCIE2A OCIE2
82 #endif
83
84
85 /** HW dependent timer initialization  */
86 #if (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE0)
87
88         static void timer_hw_init(void)
89         {
90                 cpuflags_t flags;
91                 IRQ_SAVE_DISABLE(flags);
92
93                 /* Reset Timer flags */
94                 REG_TIFR0 = BV(BIT_OCF0A) | BV(TOV0);
95
96                 /* Setup Timer/Counter interrupt */
97                 ASSR = 0x00;                  /* Internal system clock */
98                 TCCR0 = BV(WGM01)             /* Clear on Compare match */
99                         #if TIMER_PRESCALER == 64
100                                 | BV(CS02)
101                         #else
102                                 #error Unsupported value of TIMER_PRESCALER
103                         #endif
104                 ;
105                 TCNT0 = 0x00;                 /* Initialization of Timer/Counter */
106                 OCR0 = OCR_DIVISOR;           /* Timer/Counter Output Compare Register */
107
108                 /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
109                 REG_TIMSK0 &= ~BV(TOIE0);
110                 REG_TIMSK0 |= BV(OCIE0);
111
112                 IRQ_RESTORE(flags);
113         }
114
115         INLINE hptime_t timer_hw_hpread(void)
116         {
117                 return TCNT0;
118         }
119
120 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW1)
121
122         static void timer_hw_init(void)
123         {
124                 cpuflags_t flags;
125                 IRQ_SAVE_DISABLE(flags);
126
127                 /* Reset Timer overflow flag */
128                 TIFR |= BV(TOV1);
129
130                 /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
131                 #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
132                         TCCR1A |= BV(WGM11);
133                         TCCR1A &= ~BV(WGM10);
134                         TCCR1B |= BV(WGM12) | BV(CS10);
135                         TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12));
136                 /* Fast PWM mode, 8 bit, 24 kHz, no prescaling. */
137                 #elif (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 8)
138                         TCCR1A |= BV(WGM10);
139                         TCCR1A &= ~BV(WGM11);
140                         TCCR1B |= BV(WGM12) | BV(CS10);
141                         TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12));
142                 #else
143                         #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
144                 #endif
145
146                 TCNT1 = 0x00;         /* initialization of Timer/Counter */
147
148                 /* Enable timer interrupt: Timer/Counter1 Overflow */
149                 TIMSK |= BV(TOIE1);
150
151                 IRQ_RESTORE(flags);
152         }
153
154         INLINE hptime_t timer_hw_hpread(void)
155         {
156                 return TCNT1;
157         }
158
159 #elif (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE2)
160         static void timer_hw_init(void)
161         {
162                 cpuflags_t flags;
163                 IRQ_SAVE_DISABLE(flags);
164
165                 /* Reset Timer flags */
166                 REG_TIFR2 = BV(BIT_OCF2A) | BV(TOV2);
167
168                 /* Setup Timer/Counter interrupt */
169                 REG_TCCR2A = 0; // TCCR2 reg could be separate or a unique register with both A & B values, this is needed to
170                 REG_TCCR2B = 0; // ensure correct initialization.
171
172                 REG_TCCR2A = BV(WGM21);
173                 #if TIMER_PRESCALER == 64
174                 #if CPU_AVR_ATMEGA1281 || CPU_AVR_ATMEGA168
175                         // ATMega1281 & ATMega168 have undocumented differences in timer2 prescaler!
176                         REG_TCCR2B |= BV(CS22);
177                 #else
178                         REG_TCCR2B |= BV(CS21) | BV(CS20);
179                 #endif
180                 #else
181                         #error Unsupported value of TIMER_PRESCALER
182                 #endif
183
184                 /* Clear on Compare match & prescaler = 64, internal sys clock.
185                    When changing prescaler change TIMER_HW_HPTICKS_PER_SEC too */
186                 TCNT2 = 0x00;         /* initialization of Timer/Counter */
187                 REG_OCR2A = OCR_DIVISOR;   /* Timer/Counter Output Compare Register */
188
189                 /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
190                 REG_TIMSK2 &= ~BV(TOIE2);
191                 REG_TIMSK2 |= BV(BIT_OCIE2A);
192
193                 IRQ_RESTORE(flags);
194         }
195
196         INLINE hptime_t timer_hw_hpread(void)
197         {
198                 return TCNT2;
199         }
200 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW3)
201
202         static void timer_hw_init(void)
203         {
204                 cpuflags_t flags;
205                 IRQ_SAVE_DISABLE(flags);
206
207                 /* Reset Timer overflow flag */
208                 TIFR |= BV(TOV3);
209
210                 /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
211                 #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
212                         TCCR3A |= BV(WGM31);
213                         TCCR3A &= ~BV(WGM30);
214                         TCCR3B |= BV(WGM32) | BV(CS30);
215                         TCCR3B &= ~(BV(WGM33) | BV(CS31) | BV(CS32));
216                 /* Fast PWM mode, 8 bit, 24 kHz, no prescaling. */
217                 #elif (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 8)
218                         TCCR3A |= BV(WGM30);
219                         TCCR3A &= ~BV(WGM31);
220                         TCCR3B |= BV(WGM32) | BV(CS30);
221                         TCCR3B &= ~(BV(WGM33) | BV(CS31) | BV(CS32));
222                 #else
223                         #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
224                 #endif
225
226                 TCNT3 = 0x00;         /* initialization of Timer/Counter */
227
228                 /* Enable timer interrupt: Timer/Counter3 Overflow */
229                 /* ATTENTION! TOIE3 is only on ETIMSK, not TIMSK */
230                 ETIMSK |= BV(TOIE3);
231
232                 IRQ_RESTORE(flags);
233         }
234
235         INLINE hptime_t timer_hw_hpread(void)
236         {
237                 return TCNT3;
238         }
239
240 #else
241         #error Unimplemented value for CONFIG_TIMER
242 #endif /* CONFIG_TIMER */
243