Home | History | Annotate | Download | only in arduino
      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