adc.c

00001 /*
00002  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
00003  * to the MC1322x project (http://mc1322x.devl.org)
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the Institute nor the names of its contributors
00015  *    may be used to endorse or promote products derived from this software
00016  *    without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * This file is part of libmc1322x: see http://mc1322x.devl.org
00031  * for details.
00032  *
00033  *
00034  */
00035 
00036 #include <stdint.h>
00037 #include "crm.h"
00038 #include "adc.h"
00039 #include "gpio-util.h"
00040 
00041 //#define ADC_CHANS_ENABLED 0x3F // channels 0-5 enabled
00042 //#define ADC_CHANS_ENABLED 0x7E // channels 1-6 enabled
00043 //#define ADC_CHANS_ENABLED (1 << 6) // only channel 6 enabled
00044 #define ADC_CHANS_ENABLED 0x1FF // all channels, including battery reference voltage
00045 
00046 //#define ADC_PRESCALE_VALUE 24 // divide by 24 for 1MHz.
00047 
00048 #define ADC_SAMPLE_FREQ 400 // Hz (minimum of ~366.21 Hz)
00049 #define ADC_PRESCALE_VALUE (REF_OSC / ADC_SAMPLE_FREQ)
00050 
00051 #define ADC_USE_TIMER      0
00052 #define ADC_USE_INTERRUPTS 0 // incomplete support
00053 
00054 uint16_t adc_reading[NUM_ADC_CHAN];
00055 
00056 void ADC_flush(void) {
00057         while(ADC->FIFO_STATUSbits.EMPTY == 0) ADC->FIFO_READ;
00058 }
00059 
00060 uint16_t ADC_READ(void) {
00061         while(ADC->FIFO_STATUSbits.EMPTY); // loop while empty
00062         return ADC->FIFO_READ; // upper 4 bits are channel number
00063 }
00064 
00065 
00066 void adc_service(void) {
00067         uint16_t value;
00068         uint8_t channel;
00069         while (ADC->FIFO_STATUSbits.EMPTY == 0) {
00070                 value = ADC->FIFO_READ;
00071                 channel = value >> 12;
00072                 if (channel < NUM_ADC_CHAN) adc_reading[channel] = value & 0xFFF;
00073         }
00074 }
00075 
00076 void adc_init(void) {
00077         uint8_t n;
00078 
00079         ADC->CLOCK_DIVIDER = 80;       // 300 KHz
00080         ADC->PRESCALE      = ADC_PRESCALE_VALUE - 1;       // divide by 24 for 1MHz.
00081 
00082         ADC->CONTROL       = 1;
00083 
00084         // The ON-TIME must always be 10µs or greater - typical On-Time value = 0x000A (10dec)
00085         ADC->ON_TIME       = 10;
00086 
00087         /*
00088         NOTE
00089         The ADC analog block requires 6 ADC_Clocks per conversion, and the
00090         ADC_Clock must 300kHz or less. With 6 clocks/conversion and a 33.33µs
00091         clock period:
00092         * The ADC convert time must always be 20µs or greater
00093         * If the ADC_Clock is a frequency lower than 300kHz, the convert time
00094         must always be 6 ADC_Clock periods or greater
00095         * For override mode, extend convert time to 40µs minimum or greater
00096         For the convert time:
00097         * This delay is a function of the Prescale Clock (typically 1 MHz)
00098         * The register must be initialized for proper operation
00099         * For a 20µs convert time with 1MHz, value = 0x0014 (20dec)
00100         * If convert time is insufficient, inaccurate sample data will result
00101         */
00102         ADC->CONVERT_TIME  = 1000000 / (115200 / 8) - 1;
00103 
00104         ADC->MODE          = 0;        // Automatic
00105 
00106 #if ADC_USE_INTERRUPTS
00107         ADC->FIFO_CONTROL  = 7;
00108 #else
00109         ADC->FIFO_CONTROL  = 0;
00110 #endif
00111 
00112 #if ADC_USE_TIMER
00113         ADC->SR_1_HIGH       = 0x0000;
00114         ADC->SR_1_LOW        = (REF_OSC / ADC_PRESCALE_VALUE) / (115200 / 8) + 1;
00115 #endif
00116 
00117         ADC->SEQ_1         = 0
00118 #if ADC_USE_TIMER
00119                 | (1 << 15) // sequence based on Timer 1.
00120 #else
00121                 | (0 << 15) // sequence based on convert time.
00122 #endif
00123                 | ADC_CHANS_ENABLED;
00124 
00125         ADC->CONTROL       = 0xF001
00126 //#if ADC_USE_TIMER
00127                 | (1 << 1) // Timer 1 enable
00128 //#endif
00129         ;
00130         ADC->OVERRIDE     = (1 << 8);
00131 
00132         for (n=0; n<=8; n++) {
00133                 if ((ADC_CHANS_ENABLED >> n) & 1) {
00134                         gpio_select_function(30 + n, 1); // Function 1 = ADC
00135                         gpio_set_pad_dir(30 + n, PAD_DIR_INPUT);
00136                 }
00137         }
00138 }

Generated on Mon Apr 11 14:23:37 2011 for Contiki 2.5 by  doxygen 1.6.1