summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2017-01-17 14:40:43 -0800
committerScott Shawcroft <scott.shawcroft@gmail.com>2017-01-17 14:40:43 -0800
commit179413aec25e00d9b2f8d953d3390da920b99b71 (patch)
treedba8b21c708ba62cb1465b44a746a5e3561375a4
parentd239dbdc2807322c86d5dc5563dc263fa47087d1 (diff)
atmel-samd: Support multiple ADC channels at once.
Fixes #61
-rw-r--r--atmel-samd/common-hal/nativeio/AnalogIn.c56
-rw-r--r--atmel-samd/common-hal/nativeio/types.h2
2 files changed, 38 insertions, 20 deletions
diff --git a/atmel-samd/common-hal/nativeio/AnalogIn.c b/atmel-samd/common-hal/nativeio/AnalogIn.c
index 0d5f98310..37f8c13e6 100644
--- a/atmel-samd/common-hal/nativeio/AnalogIn.c
+++ b/atmel-samd/common-hal/nativeio/AnalogIn.c
@@ -26,6 +26,7 @@
#include <string.h>
+#include "py/gc.h"
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/binary.h"
@@ -35,6 +36,10 @@
#include "asf/sam0/drivers/adc/adc.h"
#include "samd21_pins.h"
+// Number of active ADC channels.
+volatile uint8_t active_channel_count;
+struct adc_module *adc_instance = NULL;
+
void common_hal_nativeio_analogin_construct(nativeio_analogin_obj_t* self,
const mcu_pin_obj_t *pin) {
if (!pin->has_adc) {
@@ -44,42 +49,55 @@ void common_hal_nativeio_analogin_construct(nativeio_analogin_obj_t* self,
self->pin = pin;
- struct adc_config config_adc;
- adc_get_config_defaults(&config_adc);
+ if (adc_instance == NULL) {
+ struct adc_config config_adc;
+ adc_get_config_defaults(&config_adc);
+
+ config_adc.reference = ADC_REFERENCE_INTVCC1;
+ config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2;
+ config_adc.positive_input = self->pin->adc_input;
+ config_adc.resolution = ADC_RESOLUTION_16BIT;
+ config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV128;
+
+ // Allocate the instance on the heap so we only use the memory when we
+ // need it.
+ adc_instance = gc_alloc(sizeof(struct adc_module), false);
- config_adc.reference = ADC_REFERENCE_INTVCC1;
- config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2;
- config_adc.positive_input = self->pin->adc_input;
- config_adc.resolution = ADC_RESOLUTION_16BIT;
- config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV128;
+ adc_init(adc_instance, ADC, &config_adc);
+ }
- adc_init(&self->adc_instance, ADC, &config_adc);
+ self->adc_instance = adc_instance;
+ active_channel_count++;
}
void common_hal_nativeio_analogin_deinit(nativeio_analogin_obj_t *self) {
- // TODO(tannewt): Count how many pins are in use and only reset the ADC when
- // none are used.
- adc_reset(&self->adc_instance);
+ active_channel_count--;
+ if (active_channel_count == 0) {
+ adc_reset(adc_instance);
+ gc_free(adc_instance);
+ // Set our reference to NULL so the GC doesn't mistakenly see the
+ // pointer in memory.
+ adc_instance = NULL;
+ }
reset_pin(self->pin->pin);
}
-// TODO(tannewt): Don't turn it all on just for one read. This simplifies
-// handling of reading multiple inputs and surviving sleep though so for now its
-// ok.
uint16_t common_hal_nativeio_analogin_get_value(nativeio_analogin_obj_t *self) {
- adc_enable(&self->adc_instance);
- adc_start_conversion(&self->adc_instance);
+ adc_set_positive_input(adc_instance, self->pin->adc_input);
+
+ adc_enable(adc_instance);
+ adc_start_conversion(adc_instance);
uint16_t data;
- enum status_code status = adc_read(&self->adc_instance, &data);
+ enum status_code status = adc_read(adc_instance, &data);
while (status == STATUS_BUSY) {
- status = adc_read(&self->adc_instance, &data);
+ status = adc_read(adc_instance, &data);
}
if (status == STATUS_ERR_OVERFLOW) {
// TODO(tannewt): Throw an error.
}
- adc_disable(&self->adc_instance);
+ adc_disable(adc_instance);
return data;
}
diff --git a/atmel-samd/common-hal/nativeio/types.h b/atmel-samd/common-hal/nativeio/types.h
index 9f83effb1..1f483eced 100644
--- a/atmel-samd/common-hal/nativeio/types.h
+++ b/atmel-samd/common-hal/nativeio/types.h
@@ -55,7 +55,7 @@
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t * pin;
- struct adc_module adc_instance;
+ struct adc_module * adc_instance;
} nativeio_analogin_obj_t;
typedef struct {