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.5 2007/03/21 11:03:56 batt
19 *#* Add missing support for ATMega1281.
21 *#* Revision 1.4 2006/07/19 12:56:26 bernie
22 *#* Convert to new Doxygen style.
24 *#* Revision 1.3 2006/06/12 21:37:02 marco
25 *#* implemented some commands (ver and sleep)
27 *#* Revision 1.2 2006/05/18 00:37:58 bernie
28 *#* Don't include unneeded header hw.h.
30 *#* Revision 1.1 2005/07/19 07:28:36 bernie
31 *#* Refactor to decouple timer ticks from milliseconds.
33 *#* Revision 1.1 2005/05/24 09:17:58 batt
34 *#* Move drivers to top-level.
37 #include <drv/timer_avr.h>
38 #include <cfg/macros.h> // BV()
40 #include <avr/interrupt.h>
43 #if CPU_AVR_ATMEGA1281
44 #define REG_TIFR0 TIFR0
45 #define REG_TIFR2 TIFR2
47 #define REG_TIMSK0 TIMSK0
48 #define REG_TIMSK2 TIMSK2
50 #define REG_TCCR2A TCCR2A
51 #define REG_TCCR2B TCCR2B
53 #define REG_OCR2A OCR2A
55 #define BIT_OCF0A OCF0A
56 #define BIT_OCF2A OCF2A
58 #define BIT_OCIE0A OCIE0A
59 #define BIT_OCIE2A OCIE2A
61 #define REG_TIFR0 TIFR
62 #define REG_TIFR2 TIFR
64 #define REG_TIMSK0 TIMSK
65 #define REG_TIMSK2 TIMSK
67 #define REG_TCCR2A TCCR2
68 #define REG_TCCR2B TCCR2
70 #define REG_OCR2A OCR2
72 #define BIT_OCF0A OCF0
73 #define BIT_OCF2A OCF2
75 #define BIT_OCIE0A OCIE0
76 #define BIT_OCIE2A OCIE2
80 /** HW dependent timer initialization */
81 #if (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE0)
83 static void timer_hw_init(void)
86 IRQ_SAVE_DISABLE(flags);
88 /* Reset Timer flags */
89 REG_TIFR0 = BV(BIT_OCF0A) | BV(TOV0);
91 /* Setup Timer/Counter interrupt */
92 ASSR = 0x00; /* Internal system clock */
93 TCCR0 = BV(WGM01) /* Clear on Compare match */
94 #if TIMER_PRESCALER == 64
97 #error Unsupported value of TIMER_PRESCALER
100 TCNT0 = 0x00; /* Initialization of Timer/Counter */
101 OCR0 = OCR_DIVISOR; /* Timer/Counter Output Compare Register */
103 /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
104 REG_TIMSK0 &= ~BV(TOIE0);
105 REG_TIMSK0 |= BV(OCIE0);
110 INLINE hptime_t timer_hw_hpread(void)
115 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW1)
117 static void timer_hw_init(void)
120 IRQ_SAVE_DISABLE(flags);
122 /* Reset Timer overflow flag */
125 /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
126 #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
128 TCCR1A &= ~BV(WGM10);
129 TCCR1B |= BV(WGM12) | BV(CS10);
130 TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12));
131 /* Fast PWM mode, 8 bit, 24 kHz, no prescaling. */
132 #elif (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 8)
134 TCCR1A &= ~BV(WGM11);
135 TCCR1B |= BV(WGM12) | BV(CS10);
136 TCCR1B &= ~(BV(WGM13) | BV(CS11) | BV(CS12));
138 #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
141 TCNT1 = 0x00; /* initialization of Timer/Counter */
143 /* Enable timer interrupt: Timer/Counter1 Overflow */
149 INLINE hptime_t timer_hw_hpread(void)
154 #elif (CONFIG_TIMER == TIMER_ON_OUTPUT_COMPARE2)
156 static void timer_hw_init(void)
159 IRQ_SAVE_DISABLE(flags);
161 /* Reset Timer flags */
162 REG_TIFR2 = BV(BIT_OCF2A) | BV(TOV2);
164 /* Setup Timer/Counter interrupt */
165 REG_TCCR2A = 0; // TCCR2 reg could be separate or a unique register with both A & B values, this is needed to
166 REG_TCCR2B = 0; // ensure correct initialization.
168 REG_TCCR2A = BV(WGM21);
169 #if TIMER_PRESCALER == 64
170 #if CPU_AVR_ATMEGA1281
171 // ATMega1281 has undocumented differences in timer2 prescaler!
172 REG_TCCR2B |= BV(CS22);
174 REG_TCCR2B |= BV(CS21) | BV(CS20);
177 #error Unsupported value of TIMER_PRESCALER
180 /* Clear on Compare match & prescaler = 64, internal sys clock.
181 When changing prescaler change TIMER_HW_HPTICKS_PER_SEC too */
182 TCNT2 = 0x00; /* initialization of Timer/Counter */
183 REG_OCR2A = OCR_DIVISOR; /* Timer/Counter Output Compare Register */
185 /* Enable timer interrupts: Timer/Counter2 Output Compare (OCIE2) */
186 REG_TIMSK2 &= ~BV(TOIE2);
187 REG_TIMSK2 |= BV(BIT_OCIE2A);
192 INLINE hptime_t timer_hw_hpread(void)
196 #elif (CONFIG_TIMER == TIMER_ON_OVERFLOW3)
198 static void timer_hw_init(void)
201 IRQ_SAVE_DISABLE(flags);
203 /* Reset Timer overflow flag */
206 /* Fast PWM mode, 9 bit, 24 kHz, no prescaling. */
207 #if (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 9)
209 TCCR3A &= ~BV(WGM30);
210 TCCR3B |= BV(WGM32) | BV(CS30);
211 TCCR3B &= ~(BV(WGM33) | BV(CS31) | BV(CS32));
212 /* Fast PWM mode, 8 bit, 24 kHz, no prescaling. */
213 #elif (TIMER_PRESCALER == 1) && (TIMER_HW_BITS == 8)
215 TCCR3A &= ~BV(WGM31);
216 TCCR3B |= BV(WGM32) | BV(CS30);
217 TCCR3B &= ~(BV(WGM33) | BV(CS31) | BV(CS32));
219 #error Unsupported value of TIMER_PRESCALER or TIMER_HW_BITS
222 TCNT3 = 0x00; /* initialization of Timer/Counter */
224 /* Enable timer interrupt: Timer/Counter3 Overflow */
225 /* ATTENTION! TOIE3 is only on ETIMSK, not TIMSK */
231 INLINE hptime_t timer_hw_hpread(void)
237 #error Unimplemented value for CONFIG_TIMER
238 #endif /* CONFIG_TIMER */