2 * Copyright Droids Corporation, Microb Technology, Eirbot (2005)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Revision : $Id: adc.c,v 1.8.4.8 2009-02-27 21:37:49 zer0 Exp $
27 /* keep the previous config */
28 static uint16_t g_adc_previous_config = ADC_NO_CONFIG;
30 /* function pointer definition for event */
31 static void (*adc_event)(int16_t) = NULL;
35 * Initialisation of ADC internal registers
36 * Can be called for a wake up after a shutdown command
40 #if defined(PRADC) && defined(PRR)
42 #elif defined(PRADC) && defined(PRR0)
46 ADCSRA = (1<<ADEN) | (ADC_PRESCALE << ADPS0);
54 * Shut down the ADC, for power consumption
56 void adc_shutdown(void)
58 ADCSRA = 0; // erases all the register
60 #if defined(PRADC) && defined(PRR)
62 #elif defined(PRADC) && defined(PRR0)
69 * Register callback event. The parameter function is called when the
70 * conversion is finished.
72 void adc_register_event(void (*f)(int16_t))
82 * Interrupt function, other interrupts are disabled during its
94 /* sign extension to fill the 16 bits when negative
95 * (for the 16 bits output format, the output is
97 if ( ( g_adc_previous_config & ADC_RESULT_SIGNED)
98 && !(g_adc_previous_config & ADC_MODE_16_BITS)
99 && (result & 0x0200) )
107 * Launch a conversion : this function launches a conversion with the
108 * specified configuration. The conversion_config is casted to an
111 void adc_launch(uint16_t conversion_config)
113 /* configure multiplexer : done first, so the maximum time is
114 * left before the real conversion launch */
115 ADMUX = conversion_config & 0xFF ;
117 * This disables and reenables the ADC when a different
118 * channel is selected AND the new channel is a differential
119 * one. Using this trick, the ADC recalibrates, and the time
120 * for this allows the amplifier to settle.
123 * When switching to a differential gain channel, the first
124 * conversion result may have a poor accuracy due to the
125 * required settling time for the automatic offset
126 * cancellation circuitry. The user should preferably
127 * disregard the first conversion result.
129 if ( (conversion_config & ADC_RESULT_SIGNED) &&
130 (g_adc_previous_config != conversion_config) ) {
136 g_adc_previous_config = conversion_config;
138 /* for some devices, one additionnal MUX bit is in ADCSRB */
139 #ifdef MUX5_IN_ADCSRB
140 if (conversion_config & MUX5_MASK_IN_CONFIG)
144 #endif // MUX5_IN_ADCSRB
146 /* Enable free run or not (triggered mode) */
147 if (conversion_config & ADC_MODE_TRIGGERED)
152 /* Start conversion, with or without enabling interrupts */
153 if (conversion_config & ADC_MODE_INT) {
154 /* Clear flag from previous intr (in case of previous
155 * conversion was not using intr), and enable
157 ADCSRA |= (1 << ADSC) | (1 << ADIF) | (1 << ADIE);
160 /* clear flag from previous int, used as a 'conversion
163 ADCSRA |= (1 << ADSC) | (1 << ADIF);
168 * This function gets an ADC value. If a conversion has been
169 * previously started, with EXACTLY the same config (or specifying
170 * ADC_NO_CONFIG) then it waits for it to finish. Else it launches a
171 * new one with the given config, and polls the result.
173 * This function should not be used if you use interrupts, but only
174 * can be used with triggered (or free run mode)
176 int16_t adc_get_value(uint16_t conversion_config)
180 /* conversion has previously been launched, or no change */
181 if ((conversion_config == ADC_NO_CONFIG) ||
182 (conversion_config == g_adc_previous_config)) {
183 if (bit_is_clear(ADCSRA, ADSC) &&
184 bit_is_clear(ADCSRA, ADIF)) {
185 /* no result is available now and no
186 conversion is pending -> launch it... */
187 adc_launch(g_adc_previous_config);
190 /* The previous conversion had a different configuration : we
191 * must launch a new one */
193 /* Cancel previous triggered mode, if it was set and
194 * reset interrupt mask */
198 /* waiting for the previous conv to finish, result will
200 while (bit_is_set(ADCSRA, ADSC));
203 adc_launch(conversion_config);
206 /* waiting for the result, works even in triggered mode, then
208 while (bit_is_clear(ADCSRA, ADIF));
213 /* If we are in SIGNED_MODE + 10 bits format, and if the
214 * result is negative, set the 7 first MSB bits to 1 */
215 if( ( g_adc_previous_config & ADC_RESULT_SIGNED ) &&
216 !(g_adc_previous_config & ADC_MODE_16_BITS) &&
217 (result & 0x0200) ) {
226 * Just a int32_t version for compatibility with control_system
227 * function prototypes.
229 int32_t adc_get_value32(void *conversion_config)
231 return adc_get_value((uint16_t)conversion_config);