4 * Copyright 2005 Develer S.r.l. (http://www.develer.com/)
5 * This file is part of DevLib - See README.devlib for information.
10 * \author Bernardo Innocenti <bernie@develer.com>
11 * \author Francesco Sacchi <batt@develer.com>
13 * \brief Low-level timer module for AVR (implementation).
18 *#* Revision 1.6 2007/06/07 14:35:12 batt
19 *#* Merge from project_ks.
21 *#* Revision 1.5 2007/03/21 11:03:56 batt
22 *#* Add missing support for ATMega1281.
24 *#* Revision 1.4 2006/07/19 12:56:26 bernie
25 *#* Convert to new Doxygen style.
27 *#* Revision 1.3 2006/06/12 21:37:02 marco
28 *#* implemented some commands (ver and sleep)
30 *#* Revision 1.2 2006/05/18 00:37:58 bernie
31 *#* Don't include unneeded header hw.h.
33 *#* Revision 1.1 2005/07/19 07:28:36 bernie
34 *#* Refactor to decouple timer ticks from milliseconds.
36 *#* Revision 1.1 2005/05/24 09:17:58 batt
37 *#* Move drivers to top-level.
40 #include <drv/timer_avr.h>
41 #include <cfg/macros.h> // BV()
45 #include <avr/interrupt.h>
48 #if CPU_AVR_ATMEGA1281 || CPU_AVR_ATMEGA168
49 #define REG_TIFR0 TIFR0
50 #define REG_TIFR2 TIFR2
52 #define REG_TIMSK0 TIMSK0
53 #define REG_TIMSK2 TIMSK2
55 #define REG_TCCR2A TCCR2A
56 #define REG_TCCR2B TCCR2B
58 #define REG_OCR2A OCR2A
60 #define BIT_OCF0A OCF0A
61 #define BIT_OCF2A OCF2A
63 #define BIT_OCIE0A OCIE0A
64 #define BIT_OCIE2A OCIE2A
66 #define REG_TIFR0 TIFR
67 #define REG_TIFR2 TIFR
69 #define REG_TIMSK0 TIMSK
70 #define REG_TIMSK2 TIMSK
72 #define REG_TCCR2A TCCR2
73 #define REG_TCCR2B TCCR2
75 #define REG_OCR2A OCR2
77 #define BIT_OCF0A OCF0
78 #define BIT_OCF2A OCF2
80 #define BIT_OCIE0A OCIE0
81 #define BIT_OCIE2A OCIE2
85 /** HW dependent timer initialization */
86 #if (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE0)
88 static void timer_hw_init(void)
91 IRQ_SAVE_DISABLE(flags);
93 /* Reset Timer flags */
94 REG_TIFR0 = BV(BIT_OCF0A) | BV(TOV0);
96 /* Setup Timer/Counter interrupt */
97 ASSR = 0x00; /* Internal system clock */
98 TCCR0 = BV(WGM01) /* Clear on Compare match */
99 #if TIMER_PRESCALER == 64
102 #error Unsupported value of TIMER_PRESCALER
105 TCNT0 = 0x00; /* Initialization of Timer/Counter */
106 OCR0 = OCR_DIVISOR; /* Timer/Counter Output Compare Register */
108 /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
109 REG_TIMSK0 &= ~BV(TOIE0);
110 REG_TIMSK0 |= BV(OCIE0);
115 INLINE hptime_t timer_hw_hpread(void)
120 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW1)
122 static void timer_hw_init(void)
125 IRQ_SAVE_DISABLE(flags);
127 /* Reset Timer overflow flag */
130 /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
131 #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
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)
139 TCCR1A &= ~BV(WGM11);
140 TCCR1B |= BV(WGM12) | BV(CS10);
141 TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12));
143 #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
146 TCNT1 = 0x00; /* initialization of Timer/Counter */
148 /* Enable timer interrupt: Timer/Counter1 Overflow */
154 INLINE hptime_t timer_hw_hpread(void)
159 #elif (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE2)
160 static void timer_hw_init(void)
163 IRQ_SAVE_DISABLE(flags);
165 /* Reset Timer flags */
166 REG_TIFR2 = BV(BIT_OCF2A) | BV(TOV2);
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.
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);
178 REG_TCCR2B |= BV(CS21) | BV(CS20);
181 #error Unsupported value of TIMER_PRESCALER
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 */
189 /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
190 REG_TIMSK2 &= ~BV(TOIE2);
191 REG_TIMSK2 |= BV(BIT_OCIE2A);
196 INLINE hptime_t timer_hw_hpread(void)
200 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW3)
202 static void timer_hw_init(void)
205 IRQ_SAVE_DISABLE(flags);
207 /* Reset Timer overflow flag */
210 /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
211 #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
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)
219 TCCR3A &= ~BV(WGM31);
220 TCCR3B |= BV(WGM32) | BV(CS30);
221 TCCR3B &= ~(BV(WGM33) | BV(CS31) | BV(CS32));
223 #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
226 TCNT3 = 0x00; /* initialization of Timer/Counter */
228 /* Enable timer interrupt: Timer/Counter3 Overflow */
229 /* ATTENTION! TOIE3 is only on ETIMSK, not TIMSK */
235 INLINE hptime_t timer_hw_hpread(void)
241 #error Unimplemented value for CONFIG_TIMER
242 #endif /* CONFIG_TIMER */