aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2017-10-15 11:49:41 -0400
committerScott Shawcroft <scott@tannewt.org>2017-10-15 16:59:23 -0700
commit8f3be0a0371d5e73930a155298804c61fd0ad902 (patch)
treec68247c38fdaa8e6f34847c98357830b8275a8ac
parentcfd1809b2bddb4c44adfd4ac187697dfa8e8cc2b (diff)
Reinit ADC completely on each call to AnalogIn.value.
-rw-r--r--atmel-samd/common-hal/analogio/AnalogIn.c76
-rw-r--r--atmel-samd/common-hal/analogio/AnalogIn.h2
-rw-r--r--atmel-samd/main.c1
3 files changed, 22 insertions, 57 deletions
diff --git a/atmel-samd/common-hal/analogio/AnalogIn.c b/atmel-samd/common-hal/analogio/AnalogIn.c
index c520b407d..03c502dff 100644
--- a/atmel-samd/common-hal/analogio/AnalogIn.c
+++ b/atmel-samd/common-hal/analogio/AnalogIn.c
@@ -38,13 +38,6 @@
#include "asf/sam0/drivers/adc/adc.h"
#include "samd21_pins.h"
-// Number of active ADC channels.
-volatile uint8_t active_channel_count;
-
-// Shared between all the instances. Allocated only when needed.
-struct adc_module *adc_instance = NULL;
-struct adc_config *config_adc = NULL;
-
void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self,
const mcu_pin_obj_t *pin) {
if (!pin->has_adc) {
@@ -54,27 +47,6 @@ void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self,
claim_pin(pin);
self->pin = pin;
-
- if (adc_instance == NULL) {
- // Allocate strucs on the heap so we only use the memory when we
- // need it.
- adc_instance = gc_alloc(sizeof(struct adc_module), false);
- config_adc = gc_alloc(sizeof(struct adc_config), false);
-
- 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;
-
- adc_init(adc_instance, ADC, config_adc);
- }
-
- self->adc_instance = adc_instance;
- self->config_adc = config_adc;
- active_channel_count++;
}
bool common_hal_analogio_analogin_deinited(analogio_analogin_obj_t *self) {
@@ -85,36 +57,30 @@ void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) {
if (common_hal_analogio_analogin_deinited(self)) {
return;
}
- active_channel_count--;
- if (active_channel_count == 0) {
- adc_reset(adc_instance);
- gc_free(adc_instance);
- gc_free(config_adc);
- // Set our references to NULL so the GC doesn't mistakenly see the
- // pointers in memory.
- adc_instance = NULL;
- config_adc = NULL;
- }
reset_pin(self->pin->pin);
self->pin = mp_const_none;
}
void analogin_reset() {
- if (adc_instance != NULL) {
- adc_reset(adc_instance);
- adc_instance = NULL;
- }
- active_channel_count = 0;
}
uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
// Something else might have used the ADC in a different way,
- // so we have to completely re-initialize it.
- // ADC must have been disabled before adc_init() is called.
- adc_init(adc_instance, ADC, config_adc);
- config_adc->positive_input = self->pin->adc_input;
+ // so we completely re-initialize it.
- adc_enable(adc_instance);
+ 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;
+
+ struct adc_module adc_instance;
+ // ADC must have been disabled before adc_init() is called.
+ adc_init(&adc_instance, ADC, &config_adc);
+ adc_enable(&adc_instance);
// Read twice and discard first result, as recommended in section 14 of
// http://www.atmel.com/images/Atmel-42645-ADC-Configurations-with-Examples_ApplicationNote_AT11481.pdf
@@ -125,23 +91,23 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
uint16_t data;
enum status_code status;
- adc_start_conversion(adc_instance);
+ adc_start_conversion(&adc_instance);
do {
- status = adc_read(adc_instance, &data);
+ status = adc_read(&adc_instance, &data);
} while (status == STATUS_BUSY);
if (status == STATUS_ERR_OVERFLOW) {
- // TODO(tannewt): Throw an error.
+ mp_raise_RuntimeError("ADC result overwritten before reading");
}
- adc_start_conversion(adc_instance);
+ adc_start_conversion(&adc_instance);
do {
- status = adc_read(adc_instance, &data);
+ status = adc_read(&adc_instance, &data);
} while (status == STATUS_BUSY);
if (status == STATUS_ERR_OVERFLOW) {
- // TODO(tannewt): Throw an error.
+ mp_raise_RuntimeError("ADC result overwritten before reading");
}
- adc_disable(adc_instance);
+ adc_disable(&adc_instance);
return data;
}
diff --git a/atmel-samd/common-hal/analogio/AnalogIn.h b/atmel-samd/common-hal/analogio/AnalogIn.h
index 3e9ddd76e..a4d5b355d 100644
--- a/atmel-samd/common-hal/analogio/AnalogIn.h
+++ b/atmel-samd/common-hal/analogio/AnalogIn.h
@@ -41,8 +41,6 @@
typedef struct {
mp_obj_base_t base;
const mcu_pin_obj_t * pin;
- struct adc_module * adc_instance;
- struct adc_config * config_adc;
} analogio_analogin_obj_t;
void analogin_reset(void);
diff --git a/atmel-samd/main.c b/atmel-samd/main.c
index 36d5dde27..fe56410c0 100644
--- a/atmel-samd/main.c
+++ b/atmel-samd/main.c
@@ -203,6 +203,7 @@ void reset_samd21(void) {
analogin_reset();
+ // TODO: move this to analogout_reset()
// Wait for the DAC to sync then reset.
while (DAC->STATUS.reg & DAC_STATUS_SYNCBUSY) {}
DAC->CTRLA.reg |= DAC_CTRLA_SWRST;