diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst index 4aac0f4b94be2..7ccdd1c3c39e1 100644 --- a/docs/library/machine.Pin.rst +++ b/docs/library/machine.Pin.rst @@ -42,7 +42,7 @@ Usage Model:: Constructors ------------ -.. class:: Pin(id, mode=-1, pull=-1, *, value=None, drive=0, alt=-1) +.. class:: Pin(id, mode=-1, pull=-1, *, value=None, drive=-1, alt=-1, slew=-1) Access the pin peripheral (GPIO pin) associated with the given ``id``. If additional arguments are given in the constructor then they are used to initialise @@ -87,9 +87,10 @@ Constructors output pin value if given, otherwise the state of the pin peripheral remains unchanged. - - ``drive`` specifies the output power of the pin and can be one of: ``Pin.DRIVE_0``, - ``Pin.DRIVE_1``, etc., increasing in drive strength. The actual current driving - capabilities are port dependent. Not all ports implement this argument. + - ``drive`` specifies the drive strength of the pin (applicable only for output pins) + and can be one of: ``Pin.DRIVE_0``, ``Pin.DRIVE_1``, etc., increasing in drive strength. + The actual current driving capabilities are port dependent. Not all ports implement this + argument. - ``alt`` specifies an alternate function for the pin and the values it can take are port dependent. This argument is valid only for ``Pin.ALT`` and ``Pin.ALT_OPEN_DRAIN`` @@ -97,6 +98,10 @@ Constructors one pin alternate function is supported the this argument is not required. Not all ports implement this argument. + - ``slew`` specifies the slew rate of the pin (applicable only for output pins) and can + be one of: ``Pin.SLEW_SLOW``, ``Pin.SLEW_FAST``, etc. The actual slew rate capabilities + are port dependent. Not all ports implement this argument. + As specified above, the Pin class allows to set an alternate function for a particular pin, but it does not specify any further operations on such a pin. Pins configured in alternate-function mode are usually not used as GPIO but are instead driven by other @@ -108,7 +113,7 @@ Constructors Methods ------- -.. method:: Pin.init(mode=-1, pull=-1, *, value=None, drive=0, alt=-1) +.. method:: Pin.init(mode=-1, pull=-1, *, value=None, drive=-1, alt=-1, slew=-1) Re-initialise the pin using the given parameters. Only those arguments that are specified will be set. The rest of the pin peripheral state will remain @@ -270,9 +275,15 @@ not all constants are available on all ports. Pin.DRIVE_1 Pin.DRIVE_2 - Selects the pin drive strength. A port may define additional drive - constants with increasing number corresponding to increasing drive - strength. + Selects the output pin drive strength. A port may define additional or + entirely custom drive constants with increasing number corresponding to + increasing drive strength. + +.. data:: Pin.SLEW_SLOW + Pin.SLEW_FAST + + Selects the output pin slew rate. A port may define additional or entirely + custom drive constants with constant corresponding to specific slew rate. .. data:: Pin.IRQ_FALLING Pin.IRQ_RISING diff --git a/docs/rp2/quickref.rst b/docs/rp2/quickref.rst index ec31442990ff4..155175a304ae1 100644 --- a/docs/rp2/quickref.rst +++ b/docs/rp2/quickref.rst @@ -162,6 +162,9 @@ Use the :ref:`machine.Pin ` class:: p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation + # create output pin on GPIO6 with 8mA drive strength and slow slew rate + p6 = Pin(6, Pin.OUT, drive=Pin.DRIVE_8, slew=Pin.SLEW_SLOW) + Programmable IO (PIO) --------------------- diff --git a/ports/rp2/machine_pin.c b/ports/rp2/machine_pin.c index 7a2de0c0bc690..09689bbc97f20 100644 --- a/ports/rp2/machine_pin.c +++ b/ports/rp2/machine_pin.c @@ -195,11 +195,26 @@ static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin machine_pin_obj_t *self = self_in; uint funcsel = gpio_get_function(self->id); qstr mode_qst; + bool is_output; + mp_uint_t drive; + mp_uint_t slew; + static const qstr drive2str[] = { + [GPIO_DRIVE_STRENGTH_2MA] = MP_QSTR_DRIVE_2, + [GPIO_DRIVE_STRENGTH_4MA] = MP_QSTR_DRIVE_4, + [GPIO_DRIVE_STRENGTH_8MA] = MP_QSTR_DRIVE_8, + [GPIO_DRIVE_STRENGTH_12MA] = MP_QSTR_DRIVE_12 + }; + static const qstr slew2str[] = { + [GPIO_SLEW_RATE_SLOW] = MP_QSTR_SLEW_SLOW, + [GPIO_SLEW_RATE_FAST] = MP_QSTR_SLEW_FAST, + }; + if (!is_ext_pin(self)) { + is_output = gpio_is_dir_out(self->id); if (funcsel == GPIO_FUNC_SIO) { if (GPIO_IS_OPEN_DRAIN(self->id)) { mode_qst = MP_QSTR_OPEN_DRAIN; - } else if (gpio_is_dir_out(self->id)) { + } else if (is_output) { mode_qst = MP_QSTR_OUT; } else { mode_qst = MP_QSTR_IN; @@ -220,6 +235,12 @@ static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin mp_printf(print, ", pull=%q", MP_QSTR_PULL_DOWN); } } + + if (is_output) { + drive = (mp_uint_t)gpio_get_drive_strength(self->id); + mp_printf(print, ", drive=%q", drive2str[drive]); + } + if (funcsel != GPIO_FUNC_SIO) { const machine_pin_af_obj_t *af = machine_pin_find_alt_by_index(self, funcsel); if (af == NULL) { @@ -228,6 +249,11 @@ static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin mp_printf(print, ", alt=%q", af->name); } } + + if (is_output) { + slew = gpio_get_slew_rate(self->id); + mp_printf(print, ", slew=%q", slew2str[slew]); + } } else { #if MICROPY_HW_PIN_EXT_COUNT mode_qst = (self->is_output) ? MP_QSTR_OUT : MP_QSTR_IN; @@ -238,13 +264,20 @@ static void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin } enum { - ARG_mode, ARG_pull, ARG_value, ARG_alt + ARG_mode, + ARG_pull, + ARG_value, + ARG_drive, + ARG_alt, + ARG_slew, }; static const mp_arg_t allowed_args[] = { {MP_QSTR_mode, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, {MP_QSTR_pull, MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, {MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE}}, + {MP_QSTR_drive, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}}, {MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = GPIO_FUNC_SIO}}, + {MP_QSTR_slew, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}}, }; static mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -284,6 +317,18 @@ static mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_ gpio_put(self->id, value); } mp_hal_pin_output(self->id); + + // Configure drive strength + mp_uint_t drive = args[ARG_drive].u_int; + if (drive != -1) { + gpio_set_drive_strength(self->id, drive); + } + + // Configure slew rate + mp_uint_t slew = args[ARG_slew].u_int; + if (slew != -1) { + gpio_set_slew_rate(self->id, slew); + } } else if (mode == MACHINE_PIN_MODE_OPEN_DRAIN) { mp_hal_pin_open_drain_with_value(self->id, value == -1 ? 1 : value); } else { @@ -504,6 +549,12 @@ static const mp_rom_map_elem_t machine_pin_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(MACHINE_PIN_MODE_ALT) }, { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULL_UP) }, { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULL_DOWN) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_2), MP_ROM_INT(GPIO_DRIVE_STRENGTH_2MA) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_4), MP_ROM_INT(GPIO_DRIVE_STRENGTH_4MA) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_8), MP_ROM_INT(GPIO_DRIVE_STRENGTH_8MA) }, + { MP_ROM_QSTR(MP_QSTR_DRIVE_12), MP_ROM_INT(GPIO_DRIVE_STRENGTH_12MA) }, + { MP_ROM_QSTR(MP_QSTR_SLEW_SLOW), MP_ROM_INT(GPIO_SLEW_RATE_SLOW) }, + { MP_ROM_QSTR(MP_QSTR_SLEW_FAST), MP_ROM_INT(GPIO_SLEW_RATE_FAST) }, { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_IRQ_EDGE_RISE) }, { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_IRQ_EDGE_FALL) },