root / arduino-1.0 / hardware / arduino / cores / arduino / wiring_analog.c @ 58d82c77
History | View | Annotate | Download (6.95 KB)
1 | 58d82c77 | Tom Mullins | /*
|
---|---|---|---|
2 | wiring_analog.c - analog input and output
|
||
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 | Modified 28 September 2010 by Mark Sproul
|
||
23 | |||
24 | $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
|
||
25 | */
|
||
26 | |||
27 | #include "wiring_private.h" |
||
28 | #include "pins_arduino.h" |
||
29 | |||
30 | uint8_t analog_reference = DEFAULT; |
||
31 | |||
32 | void analogReference(uint8_t mode)
|
||
33 | { |
||
34 | // can't actually set the register here because the default setting
|
||
35 | // will connect AVCC and the AREF pin, which would cause a short if
|
||
36 | // there's something connected to AREF.
|
||
37 | analog_reference = mode; |
||
38 | } |
||
39 | |||
40 | int analogRead(uint8_t pin)
|
||
41 | { |
||
42 | uint8_t low, high; |
||
43 | |||
44 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||
45 | if (pin >= 54) pin -= 54; // allow for channel or pin numbers |
||
46 | #elif defined(__AVR_ATmega32U4__)
|
||
47 | if (pin >= 18) pin -= 18; // allow for channel or pin numbers |
||
48 | #else
|
||
49 | if (pin >= 14) pin -= 14; // allow for channel or pin numbers |
||
50 | #endif
|
||
51 | |||
52 | #if defined(__AVR_ATmega32U4__)
|
||
53 | pin = analogPinToChannel(pin); |
||
54 | ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); |
||
55 | #elif defined(ADCSRB) && defined(MUX5)
|
||
56 | // the MUX5 bit of ADCSRB selects whether we're reading from channels
|
||
57 | // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
|
||
58 | ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); |
||
59 | #endif
|
||
60 | |||
61 | // set the analog reference (high two bits of ADMUX) and select the
|
||
62 | // channel (low 4 bits). this also sets ADLAR (left-adjust result)
|
||
63 | // to 0 (the default).
|
||
64 | #if defined(ADMUX)
|
||
65 | ADMUX = (analog_reference << 6) | (pin & 0x07); |
||
66 | #endif
|
||
67 | |||
68 | // without a delay, we seem to read from the wrong channel
|
||
69 | //delay(1);
|
||
70 | |||
71 | #if defined(ADCSRA) && defined(ADCL)
|
||
72 | // start the conversion
|
||
73 | sbi(ADCSRA, ADSC); |
||
74 | |||
75 | // ADSC is cleared when the conversion finishes
|
||
76 | while (bit_is_set(ADCSRA, ADSC));
|
||
77 | |||
78 | // we have to read ADCL first; doing so locks both ADCL
|
||
79 | // and ADCH until ADCH is read. reading ADCL second would
|
||
80 | // cause the results of each conversion to be discarded,
|
||
81 | // as ADCL and ADCH would be locked when it completed.
|
||
82 | low = ADCL; |
||
83 | high = ADCH; |
||
84 | #else
|
||
85 | // we dont have an ADC, return 0
|
||
86 | low = 0;
|
||
87 | high = 0;
|
||
88 | #endif
|
||
89 | |||
90 | // combine the two bytes
|
||
91 | return (high << 8) | low; |
||
92 | } |
||
93 | |||
94 | // Right now, PWM output only works on the pins with
|
||
95 | // hardware support. These are defined in the appropriate
|
||
96 | // pins_*.c file. For the rest of the pins, we default
|
||
97 | // to digital output.
|
||
98 | void analogWrite(uint8_t pin, int val) |
||
99 | { |
||
100 | // We need to make sure the PWM output is enabled for those pins
|
||
101 | // that support it, as we turn it off when digitally reading or
|
||
102 | // writing with them. Also, make sure the pin is in output mode
|
||
103 | // for consistenty with Wiring, which doesn't require a pinMode
|
||
104 | // call for the analog output pins.
|
||
105 | pinMode(pin, OUTPUT); |
||
106 | if (val == 0) |
||
107 | { |
||
108 | digitalWrite(pin, LOW); |
||
109 | } |
||
110 | else if (val == 255) |
||
111 | { |
||
112 | digitalWrite(pin, HIGH); |
||
113 | } |
||
114 | else
|
||
115 | { |
||
116 | switch(digitalPinToTimer(pin))
|
||
117 | { |
||
118 | // XXX fix needed for atmega8
|
||
119 | #if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__)
|
||
120 | case TIMER0A:
|
||
121 | // connect pwm to pin on timer 0
|
||
122 | sbi(TCCR0, COM00); |
||
123 | OCR0 = val; // set pwm duty
|
||
124 | break;
|
||
125 | #endif
|
||
126 | |||
127 | #if defined(TCCR0A) && defined(COM0A1)
|
||
128 | case TIMER0A:
|
||
129 | // connect pwm to pin on timer 0, channel A
|
||
130 | sbi(TCCR0A, COM0A1); |
||
131 | OCR0A = val; // set pwm duty
|
||
132 | break;
|
||
133 | #endif
|
||
134 | |||
135 | #if defined(TCCR0A) && defined(COM0B1)
|
||
136 | case TIMER0B:
|
||
137 | // connect pwm to pin on timer 0, channel B
|
||
138 | sbi(TCCR0A, COM0B1); |
||
139 | OCR0B = val; // set pwm duty
|
||
140 | break;
|
||
141 | #endif
|
||
142 | |||
143 | #if defined(TCCR1A) && defined(COM1A1)
|
||
144 | case TIMER1A:
|
||
145 | // connect pwm to pin on timer 1, channel A
|
||
146 | sbi(TCCR1A, COM1A1); |
||
147 | OCR1A = val; // set pwm duty
|
||
148 | break;
|
||
149 | #endif
|
||
150 | |||
151 | #if defined(TCCR1A) && defined(COM1B1)
|
||
152 | case TIMER1B:
|
||
153 | // connect pwm to pin on timer 1, channel B
|
||
154 | sbi(TCCR1A, COM1B1); |
||
155 | OCR1B = val; // set pwm duty
|
||
156 | break;
|
||
157 | #endif
|
||
158 | |||
159 | #if defined(TCCR2) && defined(COM21)
|
||
160 | case TIMER2:
|
||
161 | // connect pwm to pin on timer 2
|
||
162 | sbi(TCCR2, COM21); |
||
163 | OCR2 = val; // set pwm duty
|
||
164 | break;
|
||
165 | #endif
|
||
166 | |||
167 | #if defined(TCCR2A) && defined(COM2A1)
|
||
168 | case TIMER2A:
|
||
169 | // connect pwm to pin on timer 2, channel A
|
||
170 | sbi(TCCR2A, COM2A1); |
||
171 | OCR2A = val; // set pwm duty
|
||
172 | break;
|
||
173 | #endif
|
||
174 | |||
175 | #if defined(TCCR2A) && defined(COM2B1)
|
||
176 | case TIMER2B:
|
||
177 | // connect pwm to pin on timer 2, channel B
|
||
178 | sbi(TCCR2A, COM2B1); |
||
179 | OCR2B = val; // set pwm duty
|
||
180 | break;
|
||
181 | #endif
|
||
182 | |||
183 | #if defined(TCCR3A) && defined(COM3A1)
|
||
184 | case TIMER3A:
|
||
185 | // connect pwm to pin on timer 3, channel A
|
||
186 | sbi(TCCR3A, COM3A1); |
||
187 | OCR3A = val; // set pwm duty
|
||
188 | break;
|
||
189 | #endif
|
||
190 | |||
191 | #if defined(TCCR3A) && defined(COM3B1)
|
||
192 | case TIMER3B:
|
||
193 | // connect pwm to pin on timer 3, channel B
|
||
194 | sbi(TCCR3A, COM3B1); |
||
195 | OCR3B = val; // set pwm duty
|
||
196 | break;
|
||
197 | #endif
|
||
198 | |||
199 | #if defined(TCCR3A) && defined(COM3C1)
|
||
200 | case TIMER3C:
|
||
201 | // connect pwm to pin on timer 3, channel C
|
||
202 | sbi(TCCR3A, COM3C1); |
||
203 | OCR3C = val; // set pwm duty
|
||
204 | break;
|
||
205 | #endif
|
||
206 | |||
207 | #if defined(TCCR4A) && defined(COM4A1)
|
||
208 | case TIMER4A:
|
||
209 | // connect pwm to pin on timer 4, channel A
|
||
210 | sbi(TCCR4A, COM4A1); |
||
211 | OCR4A = val; // set pwm duty
|
||
212 | break;
|
||
213 | #endif
|
||
214 | |||
215 | #if defined(TCCR4A) && defined(COM4B1)
|
||
216 | case TIMER4B:
|
||
217 | // connect pwm to pin on timer 4, channel B
|
||
218 | sbi(TCCR4A, COM4B1); |
||
219 | OCR4B = val; // set pwm duty
|
||
220 | break;
|
||
221 | #endif
|
||
222 | |||
223 | #if defined(TCCR4A) && defined(COM4C1)
|
||
224 | case TIMER4C:
|
||
225 | // connect pwm to pin on timer 4, channel C
|
||
226 | sbi(TCCR4A, COM4C1); |
||
227 | OCR4C = val; // set pwm duty
|
||
228 | break;
|
||
229 | #endif
|
||
230 | |||
231 | #if defined(TCCR4A) && defined(COM4D1)
|
||
232 | case TIMER4D:
|
||
233 | // connect pwm to pin on timer 4, channel D
|
||
234 | sbi(TCCR4A, COM4D1); |
||
235 | OCR4D = val; // set pwm duty
|
||
236 | break;
|
||
237 | #endif
|
||
238 | |||
239 | #if defined(TCCR5A) && defined(COM5A1)
|
||
240 | case TIMER5A:
|
||
241 | // connect pwm to pin on timer 5, channel A
|
||
242 | sbi(TCCR5A, COM5A1); |
||
243 | OCR5A = val; // set pwm duty
|
||
244 | break;
|
||
245 | #endif
|
||
246 | |||
247 | #if defined(TCCR5A) && defined(COM5B1)
|
||
248 | case TIMER5B:
|
||
249 | // connect pwm to pin on timer 5, channel B
|
||
250 | sbi(TCCR5A, COM5B1); |
||
251 | OCR5B = val; // set pwm duty
|
||
252 | break;
|
||
253 | #endif
|
||
254 | |||
255 | #if defined(TCCR5A) && defined(COM5C1)
|
||
256 | case TIMER5C:
|
||
257 | // connect pwm to pin on timer 5, channel C
|
||
258 | sbi(TCCR5A, COM5C1); |
||
259 | OCR5C = val; // set pwm duty
|
||
260 | break;
|
||
261 | #endif
|
||
262 | |||
263 | case NOT_ON_TIMER:
|
||
264 | default:
|
||
265 | if (val < 128) { |
||
266 | digitalWrite(pin, LOW); |
||
267 | } else {
|
||
268 | digitalWrite(pin, HIGH); |
||
269 | } |
||
270 | } |
||
271 | } |
||
272 | } |