From db5f99c63ebee26a32e66f345ae0502f1004aa61 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 4 Jan 2022 14:15:20 -0600 Subject: [PATCH] Add a function to get low level register access The port is free to return NULL for any/all of these, and the caller has to check. This will be used in the floppy code, because aside from getting the registers, it looks like all is independent of MCU. --- .../common-hal/digitalio/DigitalInOut.c | 27 +++++++++++++++++++ .../common-hal/digitalio/DigitalInOut.c | 25 +++++++++++++++++ shared-bindings/digitalio/DigitalInOut.h | 11 ++++++++ 3 files changed, 63 insertions(+) diff --git a/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c b/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c index 40637bef4b..dee927ce88 100644 --- a/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c +++ b/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c @@ -187,3 +187,30 @@ digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( } } } + +bool common_hal_digitalio_has_reg_op(digitalinout_reg_op_t op) { + return true; +} + +volatile uint32_t *common_hal_digitalio_digitalinout_get_reg(digitalio_digitalinout_obj_t *self, digitalinout_reg_op_t op, uint32_t *mask) { + const uint8_t pin = self->pin->number; + int port = GPIO_PORT(pin); + + *mask = 1u << GPIO_PIN(pin); + + + switch (op) { + case DIGITALINOUT_REG_READ: + return (volatile uint32_t *)&PORT->Group[port].IN.reg; + case DIGITALINOUT_REG_WRITE: + return &PORT->Group[port].OUT.reg; + case DIGITALINOUT_REG_SET: + return &PORT->Group[port].OUTSET.reg; + case DIGITALINOUT_REG_RESET: + return &PORT->Group[port].OUTCLR.reg; + case DIGITALINOUT_REG_TOGGLE: + return &PORT->Group[port].OUTTGL.reg; + default: + return NULL; + } +} diff --git a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c index 22a61afa3f..a8a5a6b4d9 100644 --- a/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c +++ b/ports/raspberrypi/common-hal/digitalio/DigitalInOut.c @@ -164,3 +164,28 @@ digitalio_pull_t common_hal_digitalio_digitalinout_get_pull( } return PULL_NONE; } + +bool common_hal_digitalio_has_reg_op(digitalinout_reg_op_t op) { + return true; +} + +volatile uint32_t *common_hal_digitalio_digitalinout_get_reg(digitalio_digitalinout_obj_t *self, digitalinout_reg_op_t op, uint32_t *mask) { + const uint8_t pin = self->pin->number; + + *mask = 1u << pin; + + switch (op) { + case DIGITALINOUT_REG_READ: + return (volatile uint32_t *)&sio_hw->gpio_in; + case DIGITALINOUT_REG_WRITE: + return &sio_hw->gpio_out; + case DIGITALINOUT_REG_SET: + return &sio_hw->gpio_set; + case DIGITALINOUT_REG_RESET: + return &sio_hw->gpio_clr; + case DIGITALINOUT_REG_TOGGLE: + return &sio_hw->gpio_togl; + default: + return NULL; + } +} diff --git a/shared-bindings/digitalio/DigitalInOut.h b/shared-bindings/digitalio/DigitalInOut.h index ebc94fa1a6..b6edbc63aa 100644 --- a/shared-bindings/digitalio/DigitalInOut.h +++ b/shared-bindings/digitalio/DigitalInOut.h @@ -41,6 +41,14 @@ typedef enum { DIGITALINOUT_INPUT_ONLY } digitalinout_result_t; +typedef enum { + DIGITALINOUT_REG_READ, + DIGITALINOUT_REG_WRITE, + DIGITALINOUT_REG_SET, + DIGITALINOUT_REG_RESET, + DIGITALINOUT_REG_TOGGLE, +} digitalinout_reg_op_t; + digitalinout_result_t common_hal_digitalio_digitalinout_construct(digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin); void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self); bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t *self); @@ -56,4 +64,7 @@ digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(digitalio_digitalino void common_hal_digitalio_digitalinout_never_reset(digitalio_digitalinout_obj_t *self); digitalio_digitalinout_obj_t *assert_digitalinout(mp_obj_t obj); +volatile uint32_t *common_hal_digitalio_digitalinout_get_reg(digitalio_digitalinout_obj_t *self, digitalinout_reg_op_t op, uint32_t *mask); +bool common_hal_digitalio_has_reg_op(digitalinout_reg_op_t op); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_DIGITALIO_DIGITALINOUT_H