Project

General

Profile

Revision 1406

Added by James Kong over 14 years ago

Merged analog and bom changes from analog branch. Tested and working. Fixes #560

View differences:

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