Add ability to read VOLTAGE_MONITOR on Pico W

Because this must be treated like an in-use pin for all other purposes,
unfortunately a special case must be added in shared-bindings.

Multiple AnalogIn objects for VOLTAGE_MONITOR can be created (because
in use tracking isn't working) but this causes no harm.

Testing performed: Read the monitor, then imported wifi. When the
pin state was insufficiently restored, the second step would fail
with debug messages about do_ioctl timeout.

```
import analogio, board
a = analogio.AnalogIn(board.VOLTAGE_MONITOR)
print(a.value)
import wifi
```

Closes: #7020
This commit is contained in:
Jeff Epler 2022-11-08 09:36:50 -06:00
parent 1853f49139
commit 09f6919c93
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
5 changed files with 53 additions and 8 deletions

View File

@ -123,6 +123,14 @@ const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj) {
return MP_OBJ_TO_PTR(obj);
}
const mcu_pin_obj_t *validate_obj_is_free_pin_or_gpio29(mp_obj_t obj) {
const mcu_pin_obj_t *pin = validate_obj_is_pin(obj);
if (obj != &pin_GPIO29) {
assert_pin_free(pin);
}
return pin;
}
const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj) {
const mcu_pin_obj_t *pin = validate_obj_is_pin_including_cyw43(obj);
assert_pin_free(pin);

View File

@ -32,6 +32,7 @@
extern const mp_obj_type_t cyw43_pin_type;
const mcu_pin_obj_t *validate_obj_is_free_pin_including_cyw43(mp_obj_t obj);
const mcu_pin_obj_t *validate_obj_is_free_pin_or_gpio29(mp_obj_t obj);
const mcu_pin_obj_t *validate_obj_is_pin_including_cyw43(mp_obj_t obj);
#define CONSTANT_CYW43_PM_VALUE(pm_mode, pm2_sleep_ret_ms, li_beacon_period, li_dtim_period, li_assoc) \

View File

@ -45,6 +45,10 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_GP28), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO28) },
{ MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO29) },
{ MP_ROM_QSTR(MP_QSTR_STEMMA_I2C), MP_ROM_PTR(&board_i2c_obj) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);

View File

@ -35,16 +35,26 @@
#define ADC_FIRST_PIN_NUMBER 26
#define ADC_PIN_COUNT 4
// Voltage monitor is special on Pico W, because this pin is shared between the
// voltage monitor function and the wifi function. Special handling is required
// to read the analog voltage.
#if CIRCUITPY_CYW43
#define SPECIAL_PIN(pin) (pin->number == 29)
#else
#define SPECIAL_PIN(pin) false
#endif
void common_hal_analogio_analogin_construct(analogio_analogin_obj_t *self, const mcu_pin_obj_t *pin) {
if (pin->number < ADC_FIRST_PIN_NUMBER || pin->number > ADC_FIRST_PIN_NUMBER + ADC_PIN_COUNT) {
raise_ValueError_invalid_pin();
}
adc_init();
if (!SPECIAL_PIN(pin)) {
adc_gpio_init(pin->number);
claim_pin(pin);
}
adc_gpio_init(pin->number);
claim_pin(pin);
self->pin = pin;
}
@ -57,14 +67,29 @@ void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t *self) {
return;
}
reset_pin_number(self->pin->number);
if (!SPECIAL_PIN(self->pin)) {
reset_pin_number(self->pin->number);
}
self->pin = NULL;
}
uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
adc_select_input(self->pin->number - ADC_FIRST_PIN_NUMBER);
uint16_t value = adc_read();
uint16_t value;
if (SPECIAL_PIN(self->pin)) {
common_hal_mcu_disable_interrupts();
uint32_t old_pad = padsbank0_hw->io[self->pin->number];
uint32_t old_ctrl = iobank0_hw->io[self->pin->number].ctrl;
adc_gpio_init(self->pin->number);
adc_select_input(self->pin->number - ADC_FIRST_PIN_NUMBER);
value = adc_read();
gpio_init(self->pin->number);
padsbank0_hw->io[self->pin->number] = old_pad;
iobank0_hw->io[self->pin->number].ctrl = old_ctrl;
common_hal_mcu_enable_interrupts();
} else {
adc_select_input(self->pin->number - ADC_FIRST_PIN_NUMBER);
value = adc_read();
}
// Stretch 12-bit ADC reading to 16-bit range
return (value << 4) | (value >> 8);
}

View File

@ -36,6 +36,10 @@
#include "shared-bindings/analogio/AnalogIn.h"
#include "shared-bindings/util.h"
#if CIRCUITPY_CYW43
#include "bindings/cyw43/__init__.h"
#endif
//| class AnalogIn:
//| """Read analog voltage levels
//|
@ -60,8 +64,11 @@ STATIC mp_obj_t analogio_analogin_make_new(const mp_obj_type_t *type,
mp_arg_check_num(n_args, n_kw, 1, 1, false);
// 1st argument is the pin
#if CIRCUITPY_CYW43
const mcu_pin_obj_t *pin = validate_obj_is_free_pin_or_gpio29(args[0]);
#else
const mcu_pin_obj_t *pin = validate_obj_is_free_pin(args[0]);
#endif
analogio_analogin_obj_t *self = m_new_obj(analogio_analogin_obj_t);
self->base.type = &analogio_analogin_type;
common_hal_analogio_analogin_construct(self, pin);