Mozzi  alpha 0.01.1t
sound synthesis library for Arduino
 All Classes Functions Typedefs
mozzi_analog.cpp
00001 /*
00002 This code is from
00003 http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=789581
00004 discussion between jRaskell, bobgardner, theusch, Koshchi, code by jRaskell. 
00005 
00006 Another approach discussed on the same page is to use free running mode on one channel only,
00007 with (eg. 4) two resistor voltage dividers to define each input pseudo-channel.
00008 The drawback there is lower resolution for each input because the 10-bit input 
00009 range has to be divided between them.
00010 
00011 */
00012 #include "mozzi_analog.h"
00013 
00014 
00015 #define NUM_ANALOG_INPUTS 6 
00016 
00017 
00018 static volatile int sensors[NUM_ANALOG_INPUTS];
00019 static volatile byte current_adc = 0;
00020 static volatile boolean readComplete = false; 
00021 
00022 
00034 void initADC(){
00035 // The only difference between this and vanilla arduino is ADIE, enable ADC interrupt.
00036 // Enable a2d conversions | Enable ADC Interrupt | Set a2d prescale factor to 128
00037                 ADCSRA = (1 << ADEN) | (1 << ADIE) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); 
00038 }
00039 
00040 
00041 
00056 void startRead(){
00057   current_adc = 0;
00058  
00059   //Set MUX channel
00060   ADMUX = (1 << REFS0) | current_adc;
00061   //Start A2D Conversions
00062   ADCSRA |= (1 << ADSC);
00063 }
00064 
00065 
00066 
00067 ISR(ADC_vect){
00068   static boolean secondRead = false;
00069  
00070   //Only record the second read on each channel
00071   if(secondRead){
00072     sensors[current_adc] = ADCL | (ADCH << 8); 
00073     //bobgardner: ..The compiler is clever enough to read the 10 bit value like this: val=ADC;
00074     //sensors[current_adc] = ADC;
00075     current_adc++;
00076     if(current_adc > NUM_ANALOG_INPUTS){
00077       //Sequence complete.  Stop A2D conversions
00078       readComplete = true;
00079     }
00080     else{
00081       //Switch to next channel
00082       ADMUX = (1 << REFS0) | current_adc;
00083       ADCSRA |= (1 << ADSC);
00084      
00085     }
00086     secondRead = false;
00087   }
00088   else{
00089     secondRead = true;
00090     ADCSRA |= (1 << ADSC);
00091   }
00092  
00093 } 
00094 
00095 
00096 
00108 int getSensor(unsigned char channel_num){
00109                 return sensors[channel_num];
00110 }
00111 
00112 
00113 
00114 
00123 void setupFastAnalogRead()
00124 {
00125                 // fastest predivided rate (divide by 16, giving 1Mhz) for which behaviour is defined (~16us per sample)
00126                 sbi(ADCSRA,ADPS2);
00127                 cbi(ADCSRA,ADPS1);
00128                 cbi(ADCSRA,ADPS0);
00129 }
00130 
00131 
00132 
00148 void disconnectDigitalIn(byte channel_num){
00149                 DIDR0 |= 1<<channel_num;
00150 }
00151 
00152 
00153 
00159 void reconnectDigitalIn(byte channel_num){
00160                 DIDR0 &= ~(1<<channel_num);
00161 }
00162 
00163 
00164 static unsigned char analog_reference = DEFAULT;
00165 
00181 // basically analogRead() chopped in half so the ADC conversion
00182 // can be started in one function and received in another.
00183 void startAnalogRead(unsigned char pin)
00184 {
00185 
00186 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
00187                 if (pin >= 54)
00188                                 pin -= 54; // allow for channel or pin numbers
00189 #elif defined(__AVR_ATmega32U4__)
00190 
00191                 if (pin >= 18)
00192                                 pin -= 18; // allow for channel or pin numbers
00193 #elif defined(__AVR_ATmega1284__)
00194 
00195                 if (pin >= 24)
00196                                 pin -= 24; // allow for channel or pin numbers
00197 #else
00198 
00199                 if (pin >= 14)
00200                                 pin -= 14; // allow for channel or pin numbers
00201 #endif
00202 
00203 #if defined(__AVR_ATmega32U4__)
00204 
00205                 pin = analogPinToChannel(pin);
00206                 ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
00207 #elif defined(ADCSRB) && defined(MUX5)
00208                 // the MUX5 bit of ADCSRB selects whether we're reading from channels
00209                 // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high).
00210                 ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5);
00211 #endif
00212 
00213                 // set the analog reference (high two bits of ADMUX) and select the
00214                 // channel (low 4 bits).  this also sets ADLAR (left-adjust result)
00215                 // to 0 (the default).
00216 #if defined(ADMUX)
00217 
00218                 ADMUX = (analog_reference << 6) | (pin & 0x07);
00219 #endif
00220 
00221                 // without a delay, we seem to read from the wrong channel
00222                 //delay(1);
00223 
00224 #if defined(ADCSRA) && defined(ADCL)
00225                 // start the conversion
00226                 sbi(ADCSRA, ADSC);
00227 #endif
00228 }
00229 
00241 int receiveAnalogRead()
00242 {
00243                 unsigned char low, high;
00244 #if defined(ADCSRA) && defined(ADCL)
00245                 // ADSC is cleared when the conversion finishes
00246                 while (bit_is_set(ADCSRA, ADSC))
00247                                 ;
00248 
00249                 // we have to read ADCL first; doing so locks both ADCL
00250                 // and ADCH until ADCH is read.  reading ADCL second would
00251                 // cause the results of each conversion to be discarded,
00252                 // as ADCL and ADCH would be locked when it completed.
00253                 low  = ADCL;
00254                 high = ADCH;
00255 #else
00256                 // we dont have an ADC, return 0
00257                 low  = 0;
00258                 high = 0;
00259 #endif
00260 
00261                 // combine the two bytes
00262                 return (high << 8) | low;
00263 }
00264 
00265