diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/adc.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/firmware/drivers/adc.c b/firmware/drivers/adc.c index f1a6d7e667..e5dd4c1e53 100644 --- a/firmware/drivers/adc.c +++ b/firmware/drivers/adc.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include "system.h" | 21 | #include "system.h" |
22 | #include "kernel.h" | 22 | #include "kernel.h" |
23 | #include "thread.h" | 23 | #include "thread.h" |
24 | #include "string.h" | ||
24 | #include "adc.h" | 25 | #include "adc.h" |
25 | #include "pcf50605.h" | 26 | #include "pcf50605.h" |
26 | #include "pcf50606.h" | 27 | #include "pcf50606.h" |
@@ -286,31 +287,44 @@ void adc_init(void) | |||
286 | 287 | ||
287 | struct adc_struct { | 288 | struct adc_struct { |
288 | long last_read; | 289 | long last_read; |
289 | int channelnum; | 290 | unsigned short (*conversion)(unsigned short data); |
291 | short channelnum; | ||
290 | unsigned short data; | 292 | unsigned short data; |
291 | }; | 293 | }; |
292 | 294 | ||
293 | static struct adc_struct adcdata[NUM_ADC_CHANNELS]; | 295 | static struct adc_struct adcdata[NUM_ADC_CHANNELS] IDATA_ATTR; |
294 | 296 | ||
295 | static unsigned short adc_scan(struct adc_struct *adc) | 297 | /* This takes 10 bit ADC data from the subtractor circuit and scales it to |
298 | * a 13 bit value corresponding to 0-5.4v, the resulting range is 13FB-17FA, | ||
299 | * representing 3.1-5.4v */ | ||
300 | static unsigned short ten_bit_subtractor(unsigned short data) { | ||
301 | return (data<<2)+0x13FB; | ||
302 | } | ||
303 | |||
304 | static unsigned short _adc_scan(struct adc_struct *adc) | ||
296 | { | 305 | { |
297 | unsigned short data = pcf50605_a2d_read(adc->channelnum); | 306 | unsigned short data = pcf50605_a2d_read(adc->channelnum); |
298 | /* This gives us a 13 bit value corresponding to 0-5.4 volts | 307 | if (adc->conversion) { |
299 | * The range of the value is 13FB-17FA */ | 308 | data = adc->conversion(data); |
300 | data = (data<<2)+0x13FB; | 309 | } |
301 | adc->data = data; | 310 | adc->data = data; |
302 | |||
303 | return data; | 311 | return data; |
304 | } | 312 | } |
305 | 313 | ||
314 | /* Force an ADC scan _now_ */ | ||
315 | unsigned short adc_scan(int channel) { | ||
316 | return _adc_scan(&adcdata[channel]); | ||
317 | } | ||
318 | |||
319 | /* Retrieve the ADC value, only does a scan once per second or less */ | ||
306 | unsigned short adc_read(int channel) | 320 | unsigned short adc_read(int channel) |
307 | { | 321 | { |
308 | struct adc_struct *adc = &adcdata[channel]; | 322 | struct adc_struct *adc = &adcdata[channel]; |
309 | if (adc->last_read + HZ < current_tick) { | 323 | if (adc->last_read + HZ < current_tick) { |
310 | adc->last_read = current_tick; | 324 | adc->last_read = current_tick; |
311 | return adc_scan(adc); | 325 | return _adc_scan(adc); |
312 | } else { | 326 | } else { |
313 | return adcdata[channel].data; | 327 | return adc->data; |
314 | } | 328 | } |
315 | } | 329 | } |
316 | 330 | ||
@@ -318,8 +332,9 @@ void adc_init(void) | |||
318 | { | 332 | { |
319 | struct adc_struct *adc_battery = &adcdata[ADC_BATTERY]; | 333 | struct adc_struct *adc_battery = &adcdata[ADC_BATTERY]; |
320 | adc_battery->channelnum = 0x3; /* ADCVIN1, subtractor */ | 334 | adc_battery->channelnum = 0x3; /* ADCVIN1, subtractor */ |
335 | adc_battery->conversion = ten_bit_subtractor; | ||
321 | adc_battery->last_read = current_tick; | 336 | adc_battery->last_read = current_tick; |
322 | adc_scan(adc_battery); | 337 | _adc_scan(adc_battery); |
323 | } | 338 | } |
324 | 339 | ||
325 | #elif CONFIG_CPU == PNX0101 | 340 | #elif CONFIG_CPU == PNX0101 |