Revision 1461
updated all the library code to have sensible _init behavior.
Almost all of the library components have a global variable which gets set after init and the functions inside will fail with an error code if init has not been called. Also, the init functions themselves check this variable and will bail out without doing any damage if that init has already been called
analog.c | ||
---|---|---|
49 | 49 |
* @{ |
50 | 50 |
**/ |
51 | 51 |
|
52 |
unsigned char analog_initd=0; |
|
53 |
|
|
52 | 54 |
volatile int adc_loop_status = ADC_LOOP_STOPPED; |
53 | 55 |
volatile int adc_sig_stop_loop = 0; |
54 | 56 |
volatile int adc_current_port = 0; |
... | ... | |
58 | 60 |
* Initializes the ADC. |
59 | 61 |
* Call analog_init before reading from the analog ports. |
60 | 62 |
* |
63 |
* @return returns 0 on success, nonzero on error |
|
64 |
* |
|
61 | 65 |
* @see analog8, analog10, analog_get8, analog_get10 |
62 | 66 |
* |
63 | 67 |
* @bug First conversion takes a performance penalty of |
... | ... | |
73 | 77 |
* determine highest clock speed for accurate 8-bit ADC. |
74 | 78 |
* |
75 | 79 |
**/ |
76 |
void analog_init(int start_conversion) { |
|
77 |
for (int i = 0; i < 11; i++) { |
|
78 |
an_val[i].adc10 = 0; |
|
79 |
an_val[i].adc8 = 0; |
|
80 |
} |
|
80 |
int analog_init(int start_conversion) { |
|
81 |
if(analog_initd) |
|
82 |
return ERROR_INIT_ALREADY_INITD; |
|
81 | 83 |
|
82 |
// ADMUX register |
|
83 |
// Bit 7,6 - Set voltage reference to AVcc (0b01) |
|
84 |
// Bit 5 - ADLAR set to simplify moving from register |
|
85 |
// Bit 4 - X |
|
86 |
// Bit 3:0 - Sets the current channel |
|
87 |
// Initializes to read from AN1 first (AN0 is reservered for the BOM) |
|
88 |
ADMUX = 0; |
|
89 |
ADMUX |= ADMUX_OPT | _BV(MUX0); |
|
84 |
for (int i = 0; i < 11; i++) { |
|
85 |
an_val[i].adc10 = 0; |
|
86 |
an_val[i].adc8 = 0; |
|
87 |
} |
|
90 | 88 |
|
91 |
// ADC Status Register A |
|
92 |
// Bit 7 - ADEN is set (enables analog) |
|
93 |
// Bit 6 - Start conversion bit is set (must be done once for free-running mode) |
|
94 |
// Bit 5 - Enable Auto Trigger (for free running mode) NOT DOING THIS RIGHT NOW |
|
95 |
// Bit 4 - ADC interrupt flag, 0 |
|
96 |
// Bit 3 - Enable ADC Interrupt (required to run free-running mode) |
|
97 |
// Bits 2-0 - Set to create a clock divisor of 128, to make ADC clock = 8,000,000/64 = 125kHz |
|
98 |
ADCSRA = 0; |
|
99 |
ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); |
|
89 |
// ADMUX register |
|
90 |
// Bit 7,6 - Set voltage reference to AVcc (0b01) |
|
91 |
// Bit 5 - ADLAR set to simplify moving from register |
|
92 |
// Bit 4 - X |
|
93 |
// Bit 3:0 - Sets the current channel |
|
94 |
// Initializes to read from AN1 first (AN0 is reservered for the BOM) |
|
95 |
ADMUX = 0; |
|
96 |
ADMUX |= ADMUX_OPT | _BV(MUX0); |
|
97 |
|
|
98 |
// ADC Status Register A |
|
99 |
// Bit 7 - ADEN is set (enables analog) |
|
100 |
// Bit 6 - Start conversion bit is set (must be done once for free-running mode) |
|
101 |
// Bit 5 - Enable Auto Trigger (for free running mode) NOT DOING THIS RIGHT NOW |
|
102 |
// Bit 4 - ADC interrupt flag, 0 |
|
103 |
// Bit 3 - Enable ADC Interrupt (required to run free-running mode) |
|
104 |
// Bits 2-0 - Set to create a clock divisor of 128, to make ADC clock = 8,000,000/64 = 125kHz |
|
105 |
ADCSRA = 0; |
|
106 |
ADCSRA |= _BV(ADEN) | _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); |
|
100 | 107 |
|
101 |
// Set external mux lines to outputs
|
|
102 |
DDRG |= 0x1C;
|
|
108 |
// Set external mux lines to outputs
|
|
109 |
DDRG |= 0x1C;
|
|
103 | 110 |
|
104 |
// Set up first port for conversions
|
|
105 |
set_adc_mux(0x00);
|
|
106 |
adc_current_port = AN1;
|
|
111 |
// Set up first port for conversions
|
|
112 |
set_adc_mux(0x00);
|
|
113 |
adc_current_port = AN1;
|
|
107 | 114 |
|
108 |
//Start the conversion loop if requested
|
|
109 |
if (start_conversion)
|
|
110 |
analog_start_loop();
|
|
115 |
//Start the conversion loop if requested
|
|
116 |
if (start_conversion)
|
|
117 |
analog_start_loop();
|
|
111 | 118 |
|
112 |
//Conversion loop disabled by default |
|
119 |
//Conversion loop disabled by default |
|
120 |
|
|
121 |
analog_initd=1; |
|
122 |
return 0; |
|
113 | 123 |
} |
114 | 124 |
|
115 | 125 |
/** |
... | ... | |
170 | 180 |
* Starts the analog update loop. Will continue to run |
171 | 181 |
* until analog_stop_loop is called. |
172 | 182 |
* |
183 |
* @return returns 0 on success, nonzero on error |
|
184 |
* |
|
173 | 185 |
* @see analog_stop_loop, analog_loop_status |
174 | 186 |
**/ |
175 |
void analog_start_loop(void) { |
|
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 |
} |
|
187 |
int analog_start_loop(void) { |
|
188 |
if(!analog_initd) |
|
189 |
return ERROR_LIBRARY_NOT_INITD; |
|
190 |
|
|
191 |
if(adc_loop_status != ADC_LOOP_RUNNING){ |
|
192 |
//Start the conversion, enable ADC interrupt |
|
193 |
ADCSRA |= _BV(ADIE); |
|
194 |
ADCSRA |= _BV(ADSC); |
|
195 |
adc_loop_status = ADC_LOOP_RUNNING; |
|
196 |
} |
|
197 |
|
|
198 |
return 0; |
|
182 | 199 |
} |
183 | 200 |
|
184 | 201 |
/** |
... | ... | |
187 | 204 |
* is interrupted. No further updates will be made until |
188 | 205 |
* the loop is started again. |
189 | 206 |
* |
207 |
* @return returns 0 on success, nonzero on error |
|
208 |
* |
|
190 | 209 |
* @see analog_start_loop, analog_loop_status |
191 | 210 |
**/ |
192 |
void analog_stop_loop() { |
|
193 |
//Signal to stop after the next conversion |
|
194 |
adc_sig_stop_loop = 1; |
|
211 |
int analog_stop_loop() { |
|
212 |
if(!analog_initd) |
|
213 |
return ERROR_LIBRARY_NOT_INITD; |
|
214 |
|
|
215 |
//Signal to stop after the next conversion |
|
216 |
adc_sig_stop_loop = 1; |
|
217 |
|
|
218 |
return 0; |
|
195 | 219 |
} |
196 | 220 |
|
197 | 221 |
/** |
Also available in: Unified diff