rp2/machine_adc: Add support for external ADC channels.

Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
This commit is contained in:
iabdalkader 2023-10-17 12:36:11 +02:00 committed by Damien George
parent 4358faab0c
commit 5e52389f99
3 changed files with 43 additions and 6 deletions

View File

@ -27,6 +27,7 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "hardware/adc.h"
#include "machine_pin.h"
#define ADC_IS_VALID_GPIO(gpio) ((gpio) >= 26 && (gpio) <= 29)
#define ADC_CHANNEL_FROM_GPIO(gpio) ((gpio) - 26)
@ -48,6 +49,9 @@ const mp_obj_type_t machine_adc_type;
typedef struct _machine_adc_obj_t {
mp_obj_base_t base;
uint32_t channel;
#if MICROPY_HW_ADC_EXT_COUNT
uint32_t is_ext : 1;
#endif
} machine_adc_obj_t;
STATIC void machine_adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
@ -63,6 +67,9 @@ STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, s
mp_obj_t source = all_args[0];
uint32_t channel;
bool is_ext = false;
const machine_pin_obj_t *pin = NULL;
if (mp_obj_is_int(source)) {
// Get and validate channel number.
channel = mp_obj_get_int(source);
@ -72,18 +79,35 @@ STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, s
} else {
// Get GPIO and check it has ADC capabilities.
channel = mp_hal_get_pin_obj(source);
if (!ADC_IS_VALID_GPIO(channel)) {
pin = machine_pin_find(source);
channel = pin->id;
bool valid_adc_pin = false;
#if MICROPY_HW_ADC_EXT_COUNT
is_ext = pin->is_ext;
if (is_ext) {
valid_adc_pin = machine_pin_ext_is_adc_channel(pin);
} else
#endif
{
valid_adc_pin = ADC_IS_VALID_GPIO(channel);
}
if (!valid_adc_pin) {
mp_raise_ValueError(MP_ERROR_TEXT("Pin doesn't have ADC capabilities"));
}
}
// Initialise the ADC peripheral if it's not already running.
if (!(adc_hw->cs & ADC_CS_EN_BITS)) {
if (!is_ext && !(adc_hw->cs & ADC_CS_EN_BITS)) {
adc_init();
}
if (ADC_IS_VALID_GPIO(channel)) {
if (is_ext) {
#if MICROPY_HW_ADC_EXT_COUNT
// Note external pins are mutable.
machine_pin_ext_config((machine_pin_obj_t *)pin, MACHINE_PIN_MODE_ANALOG, 0);
channel = machine_pin_ext_to_adc_channel(pin);
#endif
} else if (ADC_IS_VALID_GPIO(channel)) {
// Configure the GPIO pin in ADC mode.
adc_gpio_init(channel);
channel = ADC_CHANNEL_FROM_GPIO(channel);
@ -95,6 +119,9 @@ STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, s
// Create ADC object.
machine_adc_obj_t *o = mp_obj_malloc(machine_adc_obj_t, &machine_adc_type);
o->channel = channel;
#if MICROPY_HW_ADC_EXT_COUNT
o->is_ext = is_ext;
#endif
return MP_OBJ_FROM_PTR(o);
}
@ -102,6 +129,11 @@ STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, s
// read_u16()
STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
#if MICROPY_HW_ADC_EXT_COUNT
if (self->is_ext) {
return MP_OBJ_NEW_SMALL_INT(machine_pin_ext_read_u16(self->channel));
}
#endif
return MP_OBJ_NEW_SMALL_INT(adc_config_and_read_u16(self->channel));
}
MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16);

View File

@ -166,7 +166,7 @@ const machine_pin_af_obj_t *machine_pin_find_alt_by_index(const machine_pin_obj_
return NULL;
}
static const machine_pin_obj_t *machine_pin_find(mp_obj_t pin) {
const machine_pin_obj_t *machine_pin_find(mp_obj_t pin) {
// Is already a object of the proper type
if (mp_obj_is_type(pin, &machine_pin_type)) {
return pin;

View File

@ -34,7 +34,8 @@ enum {
MACHINE_PIN_MODE_IN = 0,
MACHINE_PIN_MODE_OUT = 1,
MACHINE_PIN_MODE_OPEN_DRAIN = 2,
MACHINE_PIN_MODE_ALT = 3
MACHINE_PIN_MODE_ALT = 3,
MACHINE_PIN_MODE_ANALOG = 4
};
typedef struct _machine_pin_af_obj_t {
@ -71,10 +72,14 @@ extern const mp_obj_type_t pin_board_pins_obj_type;
extern const mp_obj_dict_t pin_board_pins_locals_dict;
void machine_pin_ext_init(void);
bool machine_pin_ext_is_adc_channel(const machine_pin_obj_t *self);
uint32_t machine_pin_ext_to_adc_channel(const machine_pin_obj_t *self);
void machine_pin_ext_set(machine_pin_obj_t *self, bool value);
bool machine_pin_ext_get(machine_pin_obj_t *self);
uint16_t machine_pin_ext_read_u16(uint32_t channel);
void machine_pin_ext_config(machine_pin_obj_t *self, int mode, int value);
const machine_pin_obj_t *machine_pin_find(mp_obj_t pin);
const machine_pin_obj_t *machine_pin_find_named(const mp_obj_dict_t *named_pins, mp_obj_t name);
const machine_pin_af_obj_t *machine_pin_find_alt(const machine_pin_obj_t *pin, uint8_t fn);
const machine_pin_af_obj_t *machine_pin_find_alt_by_index(const machine_pin_obj_t *pin, mp_uint_t af_idx);