Revision 1406
Merged analog and bom changes from analog branch. Tested and working. Fixes #560
trunk/code/projects/libdragonfly/analog.c | ||
---|---|---|
30 | 30 |
* Contains functions for manipulating the ADC on the Dragonfly board. |
31 | 31 |
* |
32 | 32 |
* @author Colony Project, CMU Robotics Club |
33 |
* code mostly taken from fwr analog file (author: Tom Lauwers) |
|
33 |
* originally taken from fwr analog file (author: Tom Lauwers) |
|
34 |
* loop code written by Kevin Woo and James Kong |
|
34 | 35 |
**/ |
35 | 36 |
|
36 | 37 |
#include <util/delay.h> |
... | ... | |
48 | 49 |
* @{ |
49 | 50 |
**/ |
50 | 51 |
|
51 |
int adc_loop_running = 0; |
|
52 |
int adc_current_port = 0; |
|
53 |
adc_t an_val[11]; |
|
52 |
volatile int adc_loop_status = ADC_LOOP_STOPPED; |
|
53 |
volatile int adc_sig_stop_loop = 0; |
|
54 |
volatile int adc_current_port = 0; |
|
55 |
volatile adc_t an_val[11]; |
|
54 | 56 |
|
55 | 57 |
/** |
56 | 58 |
* Initializes the ADC. |
57 | 59 |
* Call analog_init before reading from the analog ports. |
58 | 60 |
* |
59 | 61 |
* @see analog8, analog10, analog_get8, analog_get10 |
62 |
* |
|
63 |
* @bug First conversion takes a performance penalty of |
|
64 |
* 25 vs. 13 ADC clock cycles of successive conversions. |
|
65 |
* Analog_init should run a dummy conversion to pre-empt |
|
66 |
* this. |
|
67 |
* |
|
68 |
* For good 10-bit precision, ACD clock must be between |
|
69 |
* 50kHz and 200kHz. Currently, ADC clock is fixed at |
|
70 |
* 125kHz using 1/64prescalar. However, most code uses |
|
71 |
* 8-bit precision which can work at ADC clock speeds |
|
72 |
* higher than 200kHz. Experimental tests needed to |
|
73 |
* determine highest clock speed for accurate 8-bit ADC. |
|
74 |
* |
|
60 | 75 |
**/ |
61 | 76 |
void analog_init(int start_conversion) { |
62 | 77 |
for (int i = 0; i < 11; i++) { |
... | ... | |
81 | 96 |
// Bit 3 - Enable ADC Interrupt (required to run free-running mode) |
82 | 97 |
// Bits 2-0 - Set to create a clock divisor of 128, to make ADC clock = 8,000,000/64 = 125kHz |
83 | 98 |
ADCSRA = 0; |
84 |
ADCSRA |= _BV(ADEN) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0);
|
|
99 |
ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); |
|
85 | 100 |
|
86 | 101 |
// Set external mux lines to outputs |
87 | 102 |
DDRG |= 0x1C; |
... | ... | |
90 | 105 |
set_adc_mux(0x00); |
91 | 106 |
adc_current_port = AN1; |
92 | 107 |
|
93 |
//Start the conversion if requested |
|
108 |
//Start the conversion loop if requested
|
|
94 | 109 |
if (start_conversion) |
95 | 110 |
analog_start_loop(); |
96 |
else |
|
97 |
analog_stop_loop();
|
|
111 |
|
|
112 |
//Conversion loop disabled by default
|
|
98 | 113 |
} |
99 | 114 |
|
100 | 115 |
/** |
... | ... | |
155 | 170 |
* Starts the analog update loop. Will continue to run |
156 | 171 |
* until analog_stop_loop is called. |
157 | 172 |
* |
158 |
* @see analog_stop_loop |
|
173 |
* @see analog_stop_loop, analog_loop_status
|
|
159 | 174 |
**/ |
160 | 175 |
void analog_start_loop(void) { |
161 |
//Start the conversion |
|
162 |
ADCSRA |= _BV(ADSC); |
|
163 |
adc_loop_running = 0x1; |
|
176 |
if(adc_loop_status != ADC_LOOP_RUNNING){ |
|
177 |
//Start the conversion, enable ADC interrupt |
|
178 |
ADCSRA |= _BV(ADIE); |
|
179 |
ADCSRA |= _BV(ADSC); |
|
180 |
adc_loop_status = ADC_LOOP_RUNNING; |
|
181 |
} |
|
164 | 182 |
} |
165 | 183 |
|
166 | 184 |
/** |
... | ... | |
169 | 187 |
* is interrupted. No further updates will be made until |
170 | 188 |
* the loop is started again. |
171 | 189 |
* |
172 |
* @see analog_start_loop |
|
190 |
* @see analog_start_loop, analog_loop_status
|
|
173 | 191 |
**/ |
174 |
void analog_stop_loop(void) {
|
|
175 |
//Stop the conversion
|
|
176 |
adc_loop_running = 0x0;
|
|
192 |
void analog_stop_loop() { |
|
193 |
//Signal to stop after the next conversion
|
|
194 |
adc_sig_stop_loop = 1;
|
|
177 | 195 |
} |
196 |
|
|
178 | 197 |
/** |
198 |
* Returns the status of loop. 0 for stopped. |
|
199 |
* 1 for running. 2 for paused. |
|
200 |
* |
|
201 |
* @see analog_start_loop, analog_stop_loop |
|
202 |
**/ |
|
203 |
int analog_loop_status(void) { |
|
204 |
return adc_loop_status; |
|
205 |
} |
|
206 |
|
|
207 |
/** |
|
179 | 208 |
* Reads an 8-bit number from an analog port. |
180 | 209 |
* analog_init must be called before using this function. |
181 | 210 |
* The analog loop must also be stopped before using this |
... | ... | |
294 | 323 |
|
295 | 324 |
|
296 | 325 |
ISR(ADC_vect) { |
297 |
static volatile int adc_prev_loop_running = 0; |
|
298 | 326 |
int adc_h = 0; |
299 | 327 |
int adc_l = 0; |
328 |
|
|
329 |
if(adc_loop_status != ADC_LOOP_RUNNING) return; |
|
300 | 330 |
|
301 | 331 |
//Store the value only if this read isn't for the BOM |
302 | 332 |
if (ADMUX != BOM_PORT) { |
... | ... | |
307 | 337 |
an_val[adc_current_port - 1].adc8 = adc_h; |
308 | 338 |
} |
309 | 339 |
|
310 |
//Save the result only if we just turned off the loop |
|
311 |
if (!adc_loop_running && !adc_prev_loop_running) |
|
312 |
return; |
|
313 |
|
|
314 |
adc_prev_loop_running = adc_loop_running; |
|
315 |
|
|
316 | 340 |
//Skip AN7 because it is not a real port |
317 | 341 |
if (adc_current_port == AN6) { |
318 | 342 |
ADMUX = ADMUX_OPT | EXT_MUX; |
... | ... | |
334 | 358 |
} |
335 | 359 |
} |
336 | 360 |
|
337 |
//Initiate next conversion only if we are running a loop |
|
338 |
if (!adc_loop_running) { |
|
361 |
//Stop loop if signal is set |
|
362 |
if(adc_sig_stop_loop) { |
|
363 |
adc_sig_stop_loop = 0; |
|
364 |
adc_loop_status = ADC_LOOP_STOPPED; |
|
339 | 365 |
return; |
340 |
} else { |
|
341 |
ADCSRA |= _BV(ADSC); |
|
342 | 366 |
} |
343 |
|
|
344 |
return; |
|
367 |
|
|
368 |
//Start next conversion |
|
369 |
ADCSRA |= _BV(ADSC); |
|
345 | 370 |
} |
346 | 371 |
|
trunk/code/projects/libdragonfly/analog.h | ||
---|---|---|
36 | 36 |
* to analog. |
37 | 37 |
|
38 | 38 |
* @author Colony Project, CMU Robotics Club, based on firefly |
39 |
* code by Tom Lauwers |
|
39 |
* originally taken from fwr analog file (author: Tom Lauwers) |
|
40 |
* loop code written by Kevin Woo and James Kong |
|
40 | 41 |
*/ |
41 | 42 |
|
42 | 43 |
#ifndef _ANALOG_H |
... | ... | |
91 | 92 |
/** @brief Analog port for the battery voltage detector **/ |
92 | 93 |
#define BATT_PORT AN11 |
93 | 94 |
|
95 |
/** @brief Analog loop status. ADC conversion running. **/ |
|
96 |
#define ADC_LOOP_RUNNING 1 |
|
97 |
/** @brief Analog loop status. No ADC conversion running.**/ |
|
98 |
#define ADC_LOOP_STOPPED 0 |
|
99 |
|
|
100 |
/** @brief Analog init parameter. Start the analog loop. **/ |
|
94 | 101 |
#define ADC_START 1 |
95 |
#define ADC_STOP 0 |
|
102 |
/** @brief Analog init parameter. Don't start the analog loop. **/ |
|
103 |
#define ADC_STOP 0 |
|
96 | 104 |
|
97 | 105 |
#define ADMUX_OPT 0x60 |
98 | 106 |
|
... | ... | |
110 | 118 |
void analog_start_loop(void); |
111 | 119 |
/** @brief Stops the analog loop. Doesn't do anything if the loop is already stopped. **/ |
112 | 120 |
void analog_stop_loop(void); |
121 |
/** @brief Returns the status of the analog loop. **/ |
|
122 |
int analog_loop_status(void); |
|
113 | 123 |
/** @brief Returns an 8-bit analog value from the look up table. Use this instead of analog_get8. **/ |
114 | 124 |
unsigned int analog8(int which); |
115 | 125 |
/** @brief Returns an 10-bit analog value from the look up table. Use this instead of analog_get10. **/ |
trunk/code/projects/libdragonfly/bom.c | ||
---|---|---|
167 | 167 |
**/ |
168 | 168 |
void bom_refresh(int bit_field) { |
169 | 169 |
int i; |
170 |
int loop_was_running = 0; |
|
170 | 171 |
|
171 |
analog_stop_loop(); |
|
172 |
//Check analog loop status |
|
173 |
if(analog_loop_status() == ADC_LOOP_RUNNING) { |
|
174 |
loop_was_running = 1; |
|
175 |
analog_stop_loop(); |
|
176 |
} |
|
172 | 177 |
|
178 |
//Read BOM values |
|
173 | 179 |
for(i = 0; i < NUM_BOM_LEDS; i++) { |
174 | 180 |
if(bit_field & 0x1) { |
175 | 181 |
bom_select(i); |
... | ... | |
178 | 184 |
bit_field = bit_field >> 1; |
179 | 185 |
} |
180 | 186 |
|
181 |
analog_start_loop(); |
|
187 |
//Restore analog loop status |
|
188 |
if(loop_was_running) |
|
189 |
analog_start_loop(); |
|
182 | 190 |
} |
183 | 191 |
|
184 | 192 |
/** |
Also available in: Unified diff