kopia lustrzana https://github.com/micropython/micropython
samd/ADC_DAC: Make adc.read_timed() and dac.write_timed() configurable.
Both together require ~1.9k of flash space, including the DMA-manager and the TC-manager. adc.read_timed() uses ~700 bytes, dac.write_timed() ~600 bytes. Signed-off-by: robert-hh <robert@hammelrath.com>pull/9624/head
rodzic
f5fd6fbe94
commit
0bc34e70ae
|
@ -30,6 +30,8 @@
|
|||
#include "dma_manager.h"
|
||||
#include "samd_soc.h"
|
||||
|
||||
#if MICROPY_HW_DMA_MANAGER
|
||||
|
||||
// Set a number of dma channels managed here. samd21 has 21 dma channels, samd51
|
||||
// has 32 channels, as defined by the lib macro DMAC_CH_NUM.
|
||||
// At first, we use a smaller number here to save RAM. May be increased as needed.
|
||||
|
@ -129,3 +131,5 @@ void dac_stop_dma(int dma_channel, bool wait) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -50,8 +50,10 @@ typedef struct _machine_adc_obj_t {
|
|||
uint8_t avg;
|
||||
uint8_t bits;
|
||||
uint8_t vref;
|
||||
#if MICROPY_PY_MACHINE_ADC_TIMED
|
||||
int8_t dma_channel;
|
||||
int8_t tc_index;
|
||||
#endif
|
||||
} machine_adc_obj_t;
|
||||
|
||||
#define DEFAULT_ADC_BITS 12
|
||||
|
@ -74,9 +76,11 @@ static uint8_t adc_vref_table[] = {
|
|||
|
||||
typedef struct _device_mgmt_t {
|
||||
bool init;
|
||||
#if MICROPY_PY_MACHINE_ADC_TIMED
|
||||
bool busy;
|
||||
mp_obj_t callback;
|
||||
mp_obj_t self;
|
||||
#endif
|
||||
} device_mgmt_t;
|
||||
|
||||
device_mgmt_t device_mgmt[ADC_INST_NUM];
|
||||
|
@ -103,10 +107,7 @@ typedef struct _device_mgmt_t {
|
|||
mp_obj_t self;
|
||||
} device_mgmt_t;
|
||||
|
||||
device_mgmt_t device_mgmt[ADC_INST_NUM] = {
|
||||
{ 0, 0, -1, MP_OBJ_NULL, MP_OBJ_NULL},
|
||||
{ 0, 0, -1, MP_OBJ_NULL, MP_OBJ_NULL}
|
||||
};
|
||||
device_mgmt_t device_mgmt[ADC_INST_NUM];
|
||||
|
||||
#endif // defined(MCU_SAMD21)
|
||||
|
||||
|
@ -123,6 +124,8 @@ static void adc_init(machine_adc_obj_t *self);
|
|||
|
||||
extern mp_int_t log2i(mp_int_t num);
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_TIMED
|
||||
|
||||
// Active just for SAMD21, stops the freerun mode
|
||||
// For SAMD51, just the INT flag is reset.
|
||||
void adc_irq_handler(int dma_channel) {
|
||||
|
@ -152,6 +155,7 @@ void adc_irq_handler(int dma_channel) {
|
|||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void mp_machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
|
@ -171,7 +175,9 @@ static mp_obj_t adc_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
|||
{ MP_QSTR_bits, MP_ARG_INT, {.u_int = DEFAULT_ADC_BITS} },
|
||||
{ MP_QSTR_average, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_ADC_AVG} },
|
||||
{ MP_QSTR_vref, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_ADC_VREF} },
|
||||
#if MICROPY_PY_MACHINE_ADC_TIMED
|
||||
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
#endif
|
||||
};
|
||||
|
||||
// Parse the arguments.
|
||||
|
@ -199,18 +205,20 @@ static mp_obj_t adc_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
|||
if (0 <= vref && vref <= MAX_ADC_VREF) {
|
||||
self->vref = vref;
|
||||
}
|
||||
// flag the device/channel as being in use.
|
||||
ch_busy_flags |= (1 << (self->adc_config.device * 16 + self->adc_config.channel));
|
||||
device_mgmt[self->adc_config.device].init = false;
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_TIMED
|
||||
device_mgmt[adc_config.device].callback = args[ARG_callback].u_obj;
|
||||
if (device_mgmt[adc_config.device].callback == mp_const_none) {
|
||||
device_mgmt[adc_config.device].callback = MP_OBJ_NULL;
|
||||
} else {
|
||||
device_mgmt[adc_config.device].self = self;
|
||||
}
|
||||
|
||||
// flag the device/channel as being in use.
|
||||
ch_busy_flags |= (1 << (self->adc_config.device * 16 + self->adc_config.channel));
|
||||
device_mgmt[self->adc_config.device].init = false;
|
||||
self->dma_channel = -1;
|
||||
self->tc_index = -1;
|
||||
#endif
|
||||
|
||||
adc_init(self);
|
||||
|
||||
|
@ -222,9 +230,12 @@ static mp_int_t mp_machine_adc_read_u16(machine_adc_obj_t *self) {
|
|||
Adc *adc = adc_bases[self->adc_config.device];
|
||||
// Set the reference voltage. Default: external AREFA.
|
||||
adc->REFCTRL.reg = adc_vref_table[self->vref];
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_TIMED
|
||||
if (device_mgmt[self->adc_config.device].busy != 0) {
|
||||
mp_raise_OSError(MP_EBUSY);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Set the reference voltage. Default: external AREFA.
|
||||
adc->REFCTRL.reg = adc_vref_table[self->vref];
|
||||
|
@ -375,6 +386,9 @@ static mp_int_t machine_adc_busy(mp_obj_t self_in) {
|
|||
return device_mgmt[self->adc_config.device].busy ? true : false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_MACHINE_ADC_TIMED
|
||||
void adc_deinit_all(void) {
|
||||
ch_busy_flags = 0;
|
||||
device_mgmt[0].init = 0;
|
||||
|
@ -384,6 +398,15 @@ void adc_deinit_all(void) {
|
|||
device_mgmt[1].dma_channel = -1;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void adc_deinit_all(void) {
|
||||
ch_busy_flags = 0;
|
||||
device_mgmt[0].init = 0;
|
||||
#if defined(MCU_SAMD51)
|
||||
device_mgmt[1].init = 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void adc_init(machine_adc_obj_t *self) {
|
||||
// ADC & clock init is done only once per ADC
|
||||
|
|
|
@ -48,15 +48,16 @@ typedef struct _dac_obj_t {
|
|||
bool initialized;
|
||||
uint8_t vref;
|
||||
mp_hal_pin_obj_t gpio_id;
|
||||
#if MICROPY_PY_MACHINE_DAC_TIMED
|
||||
int8_t dma_channel;
|
||||
int8_t tc_index;
|
||||
bool busy;
|
||||
uint32_t count;
|
||||
mp_obj_t callback;
|
||||
#endif
|
||||
} dac_obj_t;
|
||||
Dac *const dac_bases[] = DAC_INSTS;
|
||||
static void dac_init(dac_obj_t *self);
|
||||
static mp_obj_t dac_deinit(mp_obj_t self_in);
|
||||
|
||||
#if defined(MCU_SAMD21)
|
||||
|
||||
|
@ -88,6 +89,8 @@ static uint8_t dac_vref_table[] = {
|
|||
|
||||
#endif // defined SAMD21 or SAMD51
|
||||
|
||||
#if MICROPY_PY_MACHINE_DAC_TIMED
|
||||
|
||||
void dac_irq_handler(int dma_channel) {
|
||||
dac_obj_t *self;
|
||||
|
||||
|
@ -126,6 +129,8 @@ void dac_irq_handler(int dma_channel) {
|
|||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static mp_obj_t dac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
|
||||
const mp_obj_t *all_args) {
|
||||
|
||||
|
@ -133,7 +138,9 @@ static mp_obj_t dac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
|
|||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_vref, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = DEFAULT_DAC_VREF} },
|
||||
#if MICROPY_PY_MACHINE_DAC_TIMED
|
||||
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
#endif
|
||||
};
|
||||
|
||||
// Parse the arguments.
|
||||
|
@ -153,15 +160,17 @@ static mp_obj_t dac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
|
|||
self->vref = vref;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_MACHINE_DAC_TIMED
|
||||
self->callback = args[ARG_callback].u_obj;
|
||||
if (self->callback == mp_const_none) {
|
||||
self->callback = MP_OBJ_NULL;
|
||||
}
|
||||
|
||||
self->dma_channel = -1;
|
||||
self->tc_index = -1;
|
||||
self->initialized = false;
|
||||
self->busy = false;
|
||||
#endif
|
||||
|
||||
self->initialized = false;
|
||||
|
||||
dac_init(self);
|
||||
// Set the port as given in self->gpio_id as DAC
|
||||
|
@ -238,9 +247,11 @@ static mp_obj_t dac_write(mp_obj_t self_in, mp_obj_t value_in) {
|
|||
if (self->initialized == false) {
|
||||
mp_raise_OSError(MP_ENODEV);
|
||||
}
|
||||
#if MICROPY_PY_MACHINE_DAC_TIMED
|
||||
if (self->busy != false) {
|
||||
mp_raise_OSError(MP_EBUSY);
|
||||
}
|
||||
#endif
|
||||
|
||||
int value = mp_obj_get_int(value_in);
|
||||
|
||||
|
@ -257,6 +268,8 @@ static mp_obj_t dac_write(mp_obj_t self_in, mp_obj_t value_in) {
|
|||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(dac_write_obj, dac_write);
|
||||
|
||||
#if MICROPY_PY_MACHINE_DAC_TIMED
|
||||
|
||||
static mp_obj_t dac_write_timed(size_t n_args, const mp_obj_t *args) {
|
||||
Dac *dac = dac_bases[0]; // Just one DAC used
|
||||
dac_obj_t *self = args[0];
|
||||
|
@ -386,12 +399,26 @@ static mp_obj_t machine_dac_busy(mp_obj_t self_in) {
|
|||
return self->busy ? mp_const_true : mp_const_false;
|
||||
}
|
||||
static MP_DEFINE_CONST_FUN_OBJ_1(machine_dac_busy_obj, machine_dac_busy);
|
||||
#else
|
||||
|
||||
void dac_deinit_all(void) {
|
||||
// Reset the DAC to lower the current consumption as SAMD21
|
||||
dac_bases[0]->CTRLA.bit.SWRST = 1;
|
||||
dac_obj[0].initialized = false;
|
||||
#if defined(MCU_SAMD51)
|
||||
dac_obj[1].initialized = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static const mp_rom_map_elem_t dac_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&dac_write_obj) },
|
||||
#if MICROPY_PY_MACHINE_DAC_TIMED
|
||||
{ MP_ROM_QSTR(MP_QSTR_busy), MP_ROM_PTR(&machine_dac_busy_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&dac_deinit_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write_timed), MP_ROM_PTR(&dac_write_timed_obj) },
|
||||
#endif
|
||||
};
|
||||
|
||||
static MP_DEFINE_CONST_DICT(dac_locals_dict, dac_locals_dict_table);
|
||||
|
|
|
@ -90,8 +90,12 @@ void samd_main(void) {
|
|||
|
||||
soft_reset_exit:
|
||||
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
|
||||
#if MICROPY_HW_DMA_MANAGER
|
||||
dma_deinit();
|
||||
#endif
|
||||
#if MICROPY_HW_TC_MANAGER
|
||||
tc_deinit();
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_ADC
|
||||
adc_deinit_all();
|
||||
#endif
|
||||
|
|
|
@ -128,6 +128,17 @@
|
|||
#define MICROPY_PY_MACHINE_WDT_TIMEOUT_MS (1)
|
||||
#define MICROPY_PLATFORM_VERSION "ASF4"
|
||||
|
||||
#ifndef MICROPY_PY_MACHINE_DAC_TIMED
|
||||
#define MICROPY_PY_MACHINE_DAC_TIMED (1)
|
||||
#endif
|
||||
#ifndef MICROPY_PY_MACHINE_ADC_TIMED
|
||||
#define MICROPY_PY_MACHINE_ADC_TIMED (1)
|
||||
#endif
|
||||
#if MICROPY_PY_MACHINE_DAC_TIMED || MICROPY_PY_MACHINE_ADC_TIMED
|
||||
#define MICROPY_HW_DMA_MANAGER (1)
|
||||
#define MICROPY_HW_TC_MANAGER (1)
|
||||
#endif
|
||||
|
||||
#define MP_STATE_PORT MP_STATE_VM
|
||||
|
||||
// Miscellaneous settings
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include "sam.h"
|
||||
#include "tc_manager.h"
|
||||
|
||||
#if MICROPY_HW_TC_MANAGER
|
||||
|
||||
// List of channel flags: true: channel used, false: channel available
|
||||
// Two Tc instances are used by the usec counter and cannot be assigned.
|
||||
#if defined(MCU_SAMD21)
|
||||
|
@ -179,3 +181,5 @@ void tc_deinit(void) {
|
|||
instance_flag[0] = instance_flag[1] = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Ładowanie…
Reference in New Issue