1/*
2  wiring.c - Partial implementation of the Wiring API for the ATmega8.
3  Part of Arduino - http://www.arduino.cc/
4
5  Copyright (c) 2005-2006 David A. Mellis
6
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  Lesser General Public License for more details.
16
17  You should have received a copy of the GNU Lesser General
18  Public License along with this library; if not, write to the
19  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  Boston, MA  02111-1307  USA
21
22  $Id$
23*/
24
25#include "wiring_private.h"
26
27// the prescaler is set so that timer0 ticks every 64 clock cycles, and the
28// the overflow handler is called every 256 ticks.
29#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
30
31// the whole number of milliseconds per timer0 overflow
32#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
33
34// the fractional number of milliseconds per timer0 overflow. we shift right
35// by three to fit these numbers into a byte. (for the clock speeds we care
36// about - 8 and 16 MHz - this doesn't lose precision.)
37#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
38#define FRACT_MAX (1000 >> 3)
39
40volatile unsigned long timer0_overflow_count = 0;
41volatile unsigned long timer0_millis = 0;
42static unsigned char timer0_fract = 0;
43
44SIGNAL(TIMER0_OVF_vect)
45{
46	// copy these to local variables so they can be stored in registers
47	// (volatile variables must be read from memory on every access)
48	unsigned long m = timer0_millis;
49	unsigned char f = timer0_fract;
50
51	m += MILLIS_INC;
52	f += FRACT_INC;
53	if (f >= FRACT_MAX) {
54		f -= FRACT_MAX;
55		m += 1;
56	}
57
58	timer0_fract = f;
59	timer0_millis = m;
60	timer0_overflow_count++;
61}
62
63unsigned long millis()
64{
65	unsigned long m;
66	uint8_t oldSREG = SREG;
67
68	// disable interrupts while we read timer0_millis or we might get an
69	// inconsistent value (e.g. in the middle of a write to timer0_millis)
70	cli();
71	m = timer0_millis;
72	SREG = oldSREG;
73
74	return m;
75}
76
77unsigned long micros() {
78	unsigned long m;
79	uint8_t oldSREG = SREG, t;
80
81	cli();
82	m = timer0_overflow_count;
83#if defined(TCNT0)
84	t = TCNT0;
85#elif defined(TCNT0L)
86	t = TCNT0L;
87#else
88	#error TIMER 0 not defined
89#endif
90
91
92#ifdef TIFR0
93	if ((TIFR0 & _BV(TOV0)) && (t < 255))
94		m++;
95#else
96	if ((TIFR & _BV(TOV0)) && (t < 255))
97		m++;
98#endif
99
100	SREG = oldSREG;
101
102	return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
103}
104
105void delay(unsigned long ms)
106{
107	uint16_t start = (uint16_t)micros();
108
109	while (ms > 0) {
110		if (((uint16_t)micros() - start) >= 1000) {
111			ms--;
112			start += 1000;
113		}
114	}
115}
116
117/* Delay for the given number of microseconds.  Assumes a 8 or 16 MHz clock. */
118void delayMicroseconds(unsigned int us)
119{
120	// calling avrlib's delay_us() function with low values (e.g. 1 or
121	// 2 microseconds) gives delays longer than desired.
122	//delay_us(us);
123
124#if F_CPU >= 16000000L
125	// for the 16 MHz clock on most Arduino boards
126
127	// for a one-microsecond delay, simply return.  the overhead
128	// of the function call yields a delay of approximately 1 1/8 us.
129	if (--us == 0)
130		return;
131
132	// the following loop takes a quarter of a microsecond (4 cycles)
133	// per iteration, so execute it four times for each microsecond of
134	// delay requested.
135	us <<= 2;
136
137	// account for the time taken in the preceeding commands.
138	us -= 2;
139#else
140	// for the 8 MHz internal clock on the ATmega168
141
142	// for a one- or two-microsecond delay, simply return.  the overhead of
143	// the function calls takes more than two microseconds.  can't just
144	// subtract two, since us is unsigned; we'd overflow.
145	if (--us == 0)
146		return;
147	if (--us == 0)
148		return;
149
150	// the following loop takes half of a microsecond (4 cycles)
151	// per iteration, so execute it twice for each microsecond of
152	// delay requested.
153	us <<= 1;
154
155	// partially compensate for the time taken by the preceeding commands.
156	// we can't subtract any more than this or we'd overflow w/ small delays.
157	us--;
158#endif
159
160	// busy wait
161	__asm__ __volatile__ (
162		"1: sbiw %0,1" "\n\t" // 2 cycles
163		"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
164	);
165}
166
167void init()
168{
169	// this needs to be called before setup() or some functions won't
170	// work there
171	sei();
172
173	// on the ATmega168, timer 0 is also used for fast hardware pwm
174	// (using phase-correct PWM would mean that timer 0 overflowed half as often
175	// resulting in different millis() behavior on the ATmega8 and ATmega168)
176#if defined(TCCR0A) && defined(WGM01)
177	sbi(TCCR0A, WGM01);
178	sbi(TCCR0A, WGM00);
179#endif
180
181	// set timer 0 prescale factor to 64
182#if defined(__AVR_ATmega128__)
183	// CPU specific: different values for the ATmega128
184	sbi(TCCR0, CS02);
185#elif defined(TCCR0) && defined(CS01) && defined(CS00)
186	// this combination is for the standard atmega8
187	sbi(TCCR0, CS01);
188	sbi(TCCR0, CS00);
189#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
190	// this combination is for the standard 168/328/1280/2560
191	sbi(TCCR0B, CS01);
192	sbi(TCCR0B, CS00);
193#elif defined(TCCR0A) && defined(CS01) && defined(CS00)
194	// this combination is for the __AVR_ATmega645__ series
195	sbi(TCCR0A, CS01);
196	sbi(TCCR0A, CS00);
197#else
198	#error Timer 0 prescale factor 64 not set correctly
199#endif
200
201	// enable timer 0 overflow interrupt
202#if defined(TIMSK) && defined(TOIE0)
203	sbi(TIMSK, TOIE0);
204#elif defined(TIMSK0) && defined(TOIE0)
205	sbi(TIMSK0, TOIE0);
206#else
207	#error	Timer 0 overflow interrupt not set correctly
208#endif
209
210	// timers 1 and 2 are used for phase-correct hardware pwm
211	// this is better for motors as it ensures an even waveform
212	// note, however, that fast pwm mode can achieve a frequency of up
213	// 8 MHz (with a 16 MHz clock) at 50% duty cycle
214
215	TCCR1B = 0;
216
217	// set timer 1 prescale factor to 64
218#if defined(TCCR1B) && defined(CS11) && defined(CS10)
219	sbi(TCCR1B, CS11);
220	sbi(TCCR1B, CS10);
221#elif defined(TCCR1) && defined(CS11) && defined(CS10)
222	sbi(TCCR1, CS11);
223	sbi(TCCR1, CS10);
224#endif
225	// put timer 1 in 8-bit phase correct pwm mode
226#if defined(TCCR1A) && defined(WGM10)
227	sbi(TCCR1A, WGM10);
228#elif defined(TCCR1)
229	#warning this needs to be finished
230#endif
231
232	// set timer 2 prescale factor to 64
233#if defined(TCCR2) && defined(CS22)
234	sbi(TCCR2, CS22);
235#elif defined(TCCR2B) && defined(CS22)
236	sbi(TCCR2B, CS22);
237#else
238	#warning Timer 2 not finished (may not be present on this CPU)
239#endif
240
241	// configure timer 2 for phase correct pwm (8-bit)
242#if defined(TCCR2) && defined(WGM20)
243	sbi(TCCR2, WGM20);
244#elif defined(TCCR2A) && defined(WGM20)
245	sbi(TCCR2A, WGM20);
246#else
247	#warning Timer 2 not finished (may not be present on this CPU)
248#endif
249
250#if defined(TCCR3B) && defined(CS31) && defined(WGM30)
251	sbi(TCCR3B, CS31);		// set timer 3 prescale factor to 64
252	sbi(TCCR3B, CS30);
253	sbi(TCCR3A, WGM30);		// put timer 3 in 8-bit phase correct pwm mode
254#endif
255
256#if defined(TCCR4B) && defined(CS41) && defined(WGM40)
257	sbi(TCCR4B, CS41);		// set timer 4 prescale factor to 64
258	sbi(TCCR4B, CS40);
259	sbi(TCCR4A, WGM40);		// put timer 4 in 8-bit phase correct pwm mode
260#endif
261
262#if defined(TCCR5B) && defined(CS51) && defined(WGM50)
263	sbi(TCCR5B, CS51);		// set timer 5 prescale factor to 64
264	sbi(TCCR5B, CS50);
265	sbi(TCCR5A, WGM50);		// put timer 5 in 8-bit phase correct pwm mode
266#endif
267
268#if defined(ADCSRA)
269	// set a2d prescale factor to 128
270	// 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
271	// XXX: this will not work properly for other clock speeds, and
272	// this code should use F_CPU to determine the prescale factor.
273	sbi(ADCSRA, ADPS2);
274	sbi(ADCSRA, ADPS1);
275	sbi(ADCSRA, ADPS0);
276
277	// enable a2d conversions
278	sbi(ADCSRA, ADEN);
279#endif
280
281	// the bootloader connects pins 0 and 1 to the USART; disconnect them
282	// here so they can be used as normal digital i/o; they will be
283	// reconnected in Serial.begin()
284#if defined(UCSRB)
285	UCSRB = 0;
286#elif defined(UCSR0B)
287	UCSR0B = 0;
288#endif
289}
290