Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 19 additions & 8 deletions docs/library/machine.Pin.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -87,16 +87,21 @@ 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``
modes. It may be used when a pin supports more than one alternate function. If only
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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions docs/rp2/quickref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ Use the :ref:`machine.Pin <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)
---------------------

Expand Down
55 changes: 53 additions & 2 deletions ports/rp2/machine_pin.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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;
Expand All @@ -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) {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) },

Expand Down
Loading