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