Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 21 additions & 55 deletions atmel-samd/common-hal/analogio/AnalogIn.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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
Expand All @@ -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;
}

Expand Down
2 changes: 0 additions & 2 deletions atmel-samd/common-hal/analogio/AnalogIn.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions atmel-samd/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down