Skip to content

Commit

Permalink
rp2/machine_adc: Add support for external ADC channels.
Browse files Browse the repository at this point in the history
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
  • Loading branch information
iabdalkader authored and dpgeorge committed Oct 20, 2023
1 parent 4358faa commit 5e52389
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 6 deletions.
40 changes: 36 additions & 4 deletions ports/rp2/machine_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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) {
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -95,13 +119,21 @@ 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);
}

// 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);
Expand Down
2 changes: 1 addition & 1 deletion ports/rp2/machine_pin.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 6 additions & 1 deletion ports/rp2/machine_pin.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 5e52389

Please sign in to comment.