diff --git a/ports/esp8266/common-hal/analogio/AnalogIn.c b/ports/esp8266/common-hal/analogio/AnalogIn.c index d3a81272ee..e01eceabd7 100644 --- a/ports/esp8266/common-hal/analogio/AnalogIn.c +++ b/ports/esp8266/common-hal/analogio/AnalogIn.c @@ -36,14 +36,12 @@ #include "user_interface.h" -volatile bool adc_in_use __attribute__((aligned(4))) = false; - void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self, const mcu_pin_obj_t *pin) { if (pin != &pin_TOUT) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "Pin %q does not have ADC capabilities", pin->name)); } - adc_in_use = true; + claim_pin(pin); } bool common_hal_analogio_analogin_deinited(analogio_analogin_obj_t* self) { @@ -54,7 +52,7 @@ void common_hal_analogio_analogin_deinit(analogio_analogin_obj_t* self) { if (common_hal_analogio_analogin_deinited(self)) { return; } - adc_in_use = false; + reset_pin(&pin_TOUT); self->deinited = true; } diff --git a/ports/esp8266/common-hal/digitalio/DigitalInOut.c b/ports/esp8266/common-hal/digitalio/DigitalInOut.c index 7101e64145..96945737b3 100644 --- a/ports/esp8266/common-hal/digitalio/DigitalInOut.c +++ b/ports/esp8266/common-hal/digitalio/DigitalInOut.c @@ -33,11 +33,21 @@ #include "py/mphal.h" #include "shared-bindings/digitalio/DigitalInOut.h" +#include "common-hal/microcontroller/Pin.h" + +extern volatile bool gpio16_in_use; digitalinout_result_t common_hal_digitalio_digitalinout_construct( digitalio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin) { self->pin = pin; - PIN_FUNC_SELECT(self->pin->peripheral, self->pin->gpio_function); + if (self->pin->gpio_number == 16) { + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); // mux configuration for XPD_DCDC and rtc_gpio0 connection + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); //mux configuration for out enable + WRITE_PERI_REG(RTC_GPIO_ENABLE, READ_PERI_REG(RTC_GPIO_ENABLE) & ~1); //out disable + claim_pin(pin); + } else { + PIN_FUNC_SELECT(self->pin->peripheral, self->pin->gpio_function); + } return DIGITALINOUT_OK; } @@ -54,6 +64,8 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self gpio_output_set(0x0, 0x0, 0x0, pin_mask); PIN_FUNC_SELECT(self->pin->peripheral, 0); PIN_PULLUP_DIS(self->pin->peripheral); + } else { + reset_pin(self->pin); } self->pin = mp_const_none; } @@ -96,6 +108,23 @@ digitalio_direction_t common_hal_digitalio_digitalinout_get_direction( void common_hal_digitalio_digitalinout_set_value( digitalio_digitalinout_obj_t* self, bool value) { + if (self->pin->gpio_number == 16) { + if (self->open_drain && value) { + // configure GPIO16 as input with output register holding 0 + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); + WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input + WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & 1)); // out=1 + return; + } else { + int out_en = self->output; + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); + WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | out_en); + WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & ~1) | value); + return; + } + } if (value) { if (self->open_drain) { // Disable output. @@ -125,11 +154,19 @@ bool common_hal_digitalio_digitalinout_get_value( } return GPIO_INPUT_GET(self->pin->gpio_number); } else { - uint32_t pin_mask = 1 << self->pin->gpio_number; - if (self->open_drain && ((*PIN_DIR) & pin_mask) == 0) { - return true; + if (self->pin->gpio_number == 16) { + if (self->open_drain && READ_PERI_REG(RTC_GPIO_ENABLE) == 0) { + return true; + } else { + return READ_PERI_REG(RTC_GPIO_OUT) & 1; + } } else { - return ((*PIN_OUT) & pin_mask) != 0; + uint32_t pin_mask = 1 << self->pin->gpio_number; + if (self->open_drain && ((*PIN_DIR) & pin_mask) == 0) { + return true; + } else { + return ((*PIN_OUT) & pin_mask) != 0; + } } } } @@ -163,8 +200,14 @@ void common_hal_digitalio_digitalinout_set_pull( return; } if (self->pin->gpio_number == 16) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, - "Pin does not support pull.")); + // PULL_DOWN is the only hardware pull direction available on GPIO16. + // since we don't support pull down, just return without attempting + // to set pull (which won't work anyway). If PULL_UP is requested, + // raise the exception so the user knows PULL_UP is not available + if (pull != PULL_NONE){ + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "GPIO16 does not support pull up.")); + } return; } if (pull == PULL_NONE) { diff --git a/ports/esp8266/common-hal/microcontroller/Pin.c b/ports/esp8266/common-hal/microcontroller/Pin.c index 5c90f4f1a0..6d2af2d2e8 100644 --- a/ports/esp8266/common-hal/microcontroller/Pin.c +++ b/ports/esp8266/common-hal/microcontroller/Pin.c @@ -32,23 +32,49 @@ #include "eagle_soc.h" -extern volatile bool adc_in_use; +bool adc_in_use; +bool gpio16_in_use; bool common_hal_mcu_pin_is_free(const mcu_pin_obj_t* pin) { if (pin == &pin_TOUT) { return !adc_in_use; } - if (pin->gpio_number == NO_GPIO || pin->gpio_number == SPECIAL_CASE) { + if (pin == &pin_XPD_DCDC) { + return !gpio16_in_use; + } + if (pin->gpio_number == NO_GPIO) { return false; } return (READ_PERI_REG(pin->peripheral) & (PERIPHS_IO_MUX_FUNC<gpio_number)) == 0 && - (READ_PERI_REG(pin->peripheral) & PERIPHS_IO_MUX_PULLUP) == 0; + (READ_PERI_REG(pin->peripheral) & PERIPHS_IO_MUX_PULLUP) == 0; +} + +void claim_pin(const mcu_pin_obj_t* pin) { + if (pin == &pin_XPD_DCDC) { + gpio16_in_use = true; + } + if (pin == &pin_TOUT) { + adc_in_use = true; + } +} + +void reset_pin(const mcu_pin_obj_t* pin) { + if (pin == &pin_XPD_DCDC) { + // Set GPIO16 as input + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); // mux configuration for XPD_DCDC and rtc_gpio0 connection + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); //mux configuration for out enable + WRITE_PERI_REG(RTC_GPIO_ENABLE, READ_PERI_REG(RTC_GPIO_ENABLE) & ~1); //out disable + gpio16_in_use = false; + } + if (pin == &pin_TOUT) { + adc_in_use = false; + } } void reset_pins(void) { - for (int i = 0; i < 17; i++) { + for (int i = 0; i < 16; i++) { // 5 is RXD, 6 is TXD if ((i > 4 && i < 13) || i == 12) { continue; @@ -59,4 +85,11 @@ void reset_pins(void) { // Disable the pin. gpio_output_set(0x0, 0x0, 0x0, 1 << i); } -} + // Set GPIO16 as input + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); // mux configuration for XPD_DCDC and rtc_gpio0 connection + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); //mux configuration for out enable + WRITE_PERI_REG(RTC_GPIO_ENABLE, READ_PERI_REG(RTC_GPIO_ENABLE) & ~1); //out disable + + adc_in_use = false; + gpio16_in_use = false; +} \ No newline at end of file diff --git a/ports/esp8266/common-hal/microcontroller/Pin.h b/ports/esp8266/common-hal/microcontroller/Pin.h index 405557ddc9..3aa290bbd3 100644 --- a/ports/esp8266/common-hal/microcontroller/Pin.h +++ b/ports/esp8266/common-hal/microcontroller/Pin.h @@ -41,6 +41,8 @@ typedef struct { #define NO_GPIO 0xff #define SPECIAL_CASE 0xfe +void claim_pin(const mcu_pin_obj_t* pin); +void reset_pin(const mcu_pin_obj_t* pin); void reset_pins(void); #endif // MICROPY_INCLUDED_ESP8266_COMMON_HAL_MICROCONTROLLER_PIN_H