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