Skip to content

Commit

Permalink
samd/machine_adc.c: Factor out machine.adc_timed().
Browse files Browse the repository at this point in the history
After machine.ADC has been moved to extmod/machine_adc.c.
Adding adc.read_timed() and adc.busy() to extmod/machine_adc.c with
a corresponding flag to enable them.
ADC/DAC timed are by default enabled only at all SAMD51 devices and
at SAMD21 devices with an external flash for the file system.

Side changes:
- Fix a type in pin_af.c, preventing to use a second ADC channel.
- Remove a duplicate definition in mcu/samd21/mpconfigmcu.h.

Signed-off-by: robert-hh <robert@hammelrath.com>
  • Loading branch information
robert-hh committed Sep 22, 2024
1 parent 65dc19b commit 9637d30
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 38 deletions.
22 changes: 22 additions & 0 deletions extmod/machine_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,24 @@ static mp_obj_t machine_adc_read(mp_obj_t self_in) {
static MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_obj, machine_adc_read);
#endif

#if MICROPY_PY_MACHINE_ADC_READ_TIMED
// ADC.atten(value) -- this is a legacy method.
static mp_obj_t machine_adc_read_timed(mp_obj_t self_in, mp_obj_t values, mp_obj_t freq_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_int_t freq = mp_obj_get_int(freq_in);
mp_machine_adc_read_timed(self, values, freq);
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_3(machine_adc_read_timed_obj, machine_adc_read_timed);

// ADC.busy())
static mp_obj_t machine_adc_busy(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
return mp_machine_adc_busy(self);
}
static MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_busy_obj, machine_adc_busy);
#endif

static const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
#if MICROPY_PY_MACHINE_ADC_INIT
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_init_obj) },
Expand All @@ -164,6 +182,10 @@ static const mp_rom_map_elem_t machine_adc_locals_dict_table[] = {
#if MICROPY_PY_MACHINE_ADC_READ
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&machine_adc_read_obj) },
#endif
#if MICROPY_PY_MACHINE_ADC_READ_TIMED
{ MP_ROM_QSTR(MP_QSTR_read_timed), MP_ROM_PTR(&machine_adc_read_timed_obj) },
{ MP_ROM_QSTR(MP_QSTR_busy), MP_ROM_PTR(&machine_adc_busy_obj) },
#endif

// A port must add ADC class constants defining the following macro.
// It can be defined to nothing if there are no constants.
Expand Down
49 changes: 22 additions & 27 deletions ports/samd/machine_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,13 @@
// This file is never compiled standalone, it's included directly from
// extmod/machine_adc.c via MICROPY_PY_MACHINE_ADC_INCLUDEFILE.

#if MICROPY_PY_MACHINE_ADC

#include <stdint.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mperrno.h"

#include "py/mphal.h"
#include "mphalport.h"
#include "sam.h"
#include "pin_af.h"
#include "modmachine.h"
#include "samd_soc.h"
#include "dma_manager.h"
#include "tc_manager.h"
Expand All @@ -50,7 +46,7 @@ typedef struct _machine_adc_obj_t {
uint8_t avg;
uint8_t bits;
uint8_t vref;
#if MICROPY_PY_MACHINE_ADC_TIMED
#if MICROPY_PY_MACHINE_ADC_READ_TIMED
int8_t dma_channel;
int8_t tc_index;
#endif
Expand All @@ -76,7 +72,7 @@ static uint8_t adc_vref_table[] = {

typedef struct _device_mgmt_t {
bool init;
#if MICROPY_PY_MACHINE_ADC_TIMED
#if MICROPY_PY_MACHINE_ADC_READ_TIMED
bool busy;
mp_obj_t callback;
mp_obj_t self;
Expand Down Expand Up @@ -124,7 +120,7 @@ static void adc_init(machine_adc_obj_t *self);

extern mp_int_t log2i(mp_int_t num);

#if MICROPY_PY_MACHINE_ADC_TIMED
#if MICROPY_PY_MACHINE_ADC_READ_TIMED

// Active just for SAMD21, stops the freerun mode
// For SAMD51, just the INT flag is reset.
Expand Down Expand Up @@ -166,16 +162,15 @@ static void mp_machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_p
self->adc_config.channel, self->bits, 1 << self->avg, self->vref);
}

static mp_obj_t adc_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
const mp_obj_t *all_args) {
static mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {

enum { ARG_id, ARG_bits, ARG_average, ARG_vref, ARG_callback };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ },
{ 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
#if MICROPY_PY_MACHINE_ADC_READ_TIMED
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
#endif
};
Expand Down Expand Up @@ -209,7 +204,7 @@ static mp_obj_t adc_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_
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
#if MICROPY_PY_MACHINE_ADC_READ_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;
Expand All @@ -231,7 +226,7 @@ static mp_int_t mp_machine_adc_read_u16(machine_adc_obj_t *self) {
// Set the reference voltage. Default: external AREFA.
adc->REFCTRL.reg = adc_vref_table[self->vref];

#if MICROPY_PY_MACHINE_ADC_TIMED
#if MICROPY_PY_MACHINE_ADC_READ_TIMED
if (device_mgmt[self->adc_config.device].busy != 0) {
mp_raise_OSError(MP_EBUSY);
}
Expand Down Expand Up @@ -260,13 +255,13 @@ static mp_int_t mp_machine_adc_read_u16(machine_adc_obj_t *self) {
return adc->RESULT.reg * (65536 / (1 << self->bits));
}

static void machine_adc_read_timed(mp_obj_t self_in, mp_obj_t values, mp_obj_t freq_in) {
machine_adc_obj_t *self = self_in;
#if MICROPY_PY_MACHINE_ADC_READ_TIMED

static void mp_machine_adc_read_timed(machine_adc_obj_t *self, mp_obj_t values, mp_int_t freq) {
Adc *adc = adc_bases[self->adc_config.device];
mp_buffer_info_t src;
mp_get_buffer_raise(values, &src, MP_BUFFER_READ);
if (src.len >= 2) {
int freq = mp_obj_get_int(freq_in);
if (self->tc_index == -1) {
self->tc_index = allocate_tc_instance();
}
Expand Down Expand Up @@ -359,12 +354,19 @@ static void machine_adc_read_timed(mp_obj_t self_in, mp_obj_t values, mp_obj_t f
#endif // defined SAMD21 or SAMD51

}
return mp_const_none;
}

// busy() : Report, if the ADC device is busy
static mp_obj_t mp_machine_adc_busy(machine_adc_obj_t *self) {
return device_mgmt[self->adc_config.device].busy ? mp_const_true : mp_const_false;
}

#endif

// deinit() : release the ADC channel
static void mp_machine_adc_deinit(machine_adc_obj_t *self) {
busy_flags &= ~((1 << (self->adc_config.device * 16 + self->adc_config.channel)));
ch_busy_flags &= ~((1 << (self->adc_config.device * 16 + self->adc_config.channel)));
#if MICROPY_PY_MACHINE_ADC_READ_TIMED
if (self->dma_channel >= 0) {
#if defined(MCU_SAMD51)
if (self->dma_channel == device_mgmt[self->adc_config.device].dma_channel) {
Expand All @@ -380,17 +382,10 @@ static void mp_machine_adc_deinit(machine_adc_obj_t *self) {
free_tc_instance(self->tc_index);
self->tc_index = -1;
}
#endif
}

// busy() : Report, if the ADC device is busy
static mp_int_t machine_adc_busy(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
return device_mgmt[self->adc_config.device].busy ? true : false;
}

#endif

#if MICROPY_PY_MACHINE_ADC_TIMED
#if MICROPY_PY_MACHINE_ADC_READ_TIMED
void adc_deinit_all(void) {
ch_busy_flags = 0;
device_mgmt[0].init = 0;
Expand Down
7 changes: 7 additions & 0 deletions ports/samd/mcu/samd21/mpconfigmcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,13 @@ unsigned long trng_random_u32(int delay);
#define MICROPY_PY_ONEWIRE (SAMD21_EXTRA_FEATURES)
#endif

#ifndef MICROPY_PY_MACHINE_ADC_READ_TIMED
#define MICROPY_PY_MACHINE_ADC_READ_TIMED (SAMD21_EXTRA_FEATURES)
#endif
#ifndef MICROPY_PY_MACHINE_DAC_TIMED
#define MICROPY_PY_MACHINE_DAC_TIMED (SAMD21_EXTRA_FEATURES)
#endif

#ifndef MICROPY_PY_MACHINE_PIN_BOARD_CPU
#define MICROPY_PY_MACHINE_PIN_BOARD_CPU (1)
#endif
Expand Down
14 changes: 10 additions & 4 deletions ports/samd/mcu/samd51/mpconfigmcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ unsigned long trng_random_u32(void);
#define MICROPY_PY_MACHINE_UART_IRQ (1)

// fatfs configuration used in ffconf.h
#define MICROPY_FATFS_ENABLE_LFN (1)
#define MICROPY_FATFS_RPATH (2)
#define MICROPY_FATFS_MAX_SS (4096)
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */
#define MICROPY_FATFS_ENABLE_LFN (1)
#define MICROPY_FATFS_RPATH (2)
#define MICROPY_FATFS_MAX_SS (4096)
#define MICROPY_FATFS_LFN_CODE_PAGE 437 /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */

#define VFS_BLOCK_SIZE_BYTES (1536) //

Expand All @@ -31,6 +31,12 @@ unsigned long trng_random_u32(void);
#ifndef MICROPY_HW_UART_RTSCTS
#define MICROPY_HW_UART_RTSCTS (1)
#endif
#ifndef MICROPY_PY_MACHINE_ADC_READ_TIMED
#define MICROPY_PY_MACHINE_ADC_READ_TIMED (1)
#endif
#ifndef MICROPY_PY_MACHINE_DAC_TIMED
#define MICROPY_PY_MACHINE_DAC_TIMED (1)
#endif

#define CPU_FREQ (120000000)
#define DFLL48M_FREQ (48000000)
Expand Down
8 changes: 1 addition & 7 deletions ports/samd/mpconfigport.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,7 @@
#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
#if MICROPY_PY_MACHINE_DAC_TIMED || MICROPY_PY_MACHINE_ADC_READ_TIMED
#define MICROPY_HW_DMA_MANAGER (1)
#define MICROPY_HW_TC_MANAGER (1)
#endif
Expand Down

0 comments on commit 9637d30

Please sign in to comment.