Commit 2f96b198 authored by Damien George's avatar Damien George
Browse files

stmhal: Bring Pin class close to new machine module specification.

Looks like we can use the same Pin class for legacy pyb module and new
machine module.
parent bedab235
......@@ -35,6 +35,7 @@
#include "irq.h"
#include "rng.h"
#include "storage.h"
#include "pin.h"
#include "timer.h"
#include "usb.h"
......@@ -409,9 +410,11 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_disable_irq), (mp_obj_t)&pyb_disable_irq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_enable_irq), (mp_obj_t)&pyb_enable_irq_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type },
#if 0
{ MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type },
......
......@@ -260,6 +260,24 @@ STATIC mp_obj_t pin_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw,
return (mp_obj_t)pin;
}
// fast method for getting/setting pin value
STATIC mp_obj_t pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
pin_obj_t *self = self_in;
if (n_args == 0) {
// get pin
return MP_OBJ_NEW_SMALL_INT(GPIO_read_pin(self->gpio, self->pin));
} else {
// set pin
if (mp_obj_is_true(args[0])) {
GPIO_set_pin(self->gpio, self->pin_mask);
} else {
GPIO_clear_pin(self->gpio, self->pin_mask);
}
return mp_const_none;
}
}
/// \classmethod mapper([fun])
/// Get or set the pin mapper function.
STATIC mp_obj_t pin_mapper(mp_uint_t n_args, const mp_obj_t *args) {
......@@ -310,50 +328,40 @@ STATIC mp_obj_t pin_debug(mp_uint_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_debug_fun_obj, 1, 2, pin_debug);
STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, (mp_obj_t)&pin_debug_fun_obj);
/// \method init(mode, pull=Pin.PULL_NONE, af=-1)
/// Initialise the pin:
///
/// - `mode` can be one of:
/// - `Pin.IN` - configure the pin for input;
/// - `Pin.OUT_PP` - configure the pin for output, with push-pull control;
/// - `Pin.OUT_OD` - configure the pin for output, with open-drain control;
/// - `Pin.AF_PP` - configure the pin for alternate function, pull-pull;
/// - `Pin.AF_OD` - configure the pin for alternate function, open-drain;
/// - `Pin.ANALOG` - configure the pin for analog.
/// - `pull` can be one of:
/// - `Pin.PULL_NONE` - no pull up or down resistors;
/// - `Pin.PULL_UP` - enable the pull-up resistor;
/// - `Pin.PULL_DOWN` - enable the pull-down resistor.
/// - when mode is Pin.AF_PP or Pin.AF_OD, then af can be the index or name
/// of one of the alternate functions associated with a pin.
///
/// Returns: `None`.
STATIC const mp_arg_t pin_init_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_pull, MP_ARG_INT, {.u_int = GPIO_NOPULL}},
{ MP_QSTR_af, MP_ARG_INT, {.u_int = -1}},
};
#define PIN_INIT_NUM_ARGS MP_ARRAY_SIZE(pin_init_args)
// init(mode, pull=None, af=-1, *, value, alt)
STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
{ MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
{ MP_QSTR_af, MP_ARG_INT, {.u_int = -1}}, // legacy
{ MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
{ MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
};
STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t vals[PIN_INIT_NUM_ARGS];
mp_arg_parse_all(n_args, args, kw_args, PIN_INIT_NUM_ARGS, pin_init_args, vals);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get io mode
uint mode = vals[0].u_int;
uint mode = args[0].u_int;
if (!IS_GPIO_MODE(mode)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin mode: %d", mode));
}
// get pull mode
uint pull = vals[1].u_int;
uint pull = GPIO_NOPULL;
if (args[1].u_obj != mp_const_none) {
pull = mp_obj_get_int(args[1].u_obj);
}
if (!IS_GPIO_PULL(pull)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin pull: %d", pull));
}
// get af (alternate function)
mp_int_t af = vals[2].u_int;
// get af (alternate function); alt-arg overrides af-arg
mp_int_t af = args[4].u_int;
if (af == -1) {
af = args[2].u_int;
}
if ((mode == GPIO_MODE_AF_PP || mode == GPIO_MODE_AF_OD) && !IS_GPIO_AF(af)) {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin af: %d", af));
}
......@@ -361,6 +369,15 @@ STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, con
// enable the peripheral clock for the port of this pin
mp_hal_gpio_clock_enable(self->gpio);
// if given, set the pin value before initialising to prevent glitches
if (args[3].u_obj != MP_OBJ_NULL) {
if (mp_obj_is_true(args[3].u_obj)) {
GPIO_set_pin(self->gpio, self->pin_mask);
} else {
GPIO_clear_pin(self->gpio, self->pin_mask);
}
}
// configure the GPIO as requested
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.Pin = self->pin_mask;
......@@ -386,19 +403,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, pin_obj_init);
/// anything that converts to a boolean. If it converts to `True`, the pin
/// is set high, otherwise it is set low.
STATIC mp_obj_t pin_value(mp_uint_t n_args, const mp_obj_t *args) {
pin_obj_t *self = args[0];
if (n_args == 1) {
// get pin
return MP_OBJ_NEW_SMALL_INT(GPIO_read_pin(self->gpio, self->pin));
} else {
// set pin
if (mp_obj_is_true(args[1])) {
GPIO_set_pin(self->gpio, self->pin_mask);
} else {
GPIO_clear_pin(self->gpio, self->pin_mask);
}
return mp_const_none;
}
return pin_call(args[0], n_args - 1, 0, args + 1);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value);
......@@ -524,24 +529,21 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type },
// class constants
/// \constant IN - initialise the pin to input mode
/// \constant OUT_PP - initialise the pin to output mode with a push-pull drive
/// \constant OUT_OD - initialise the pin to output mode with an open-drain drive
/// \constant AF_PP - initialise the pin to alternate-function mode with a push-pull drive
/// \constant AF_OD - initialise the pin to alternate-function mode with an open-drain drive
/// \constant ANALOG - initialise the pin to analog mode
/// \constant PULL_NONE - don't enable any pull up or down resistors on the pin
/// \constant PULL_UP - enable the pull-up resistor on the pin
/// \constant PULL_DOWN - enable the pull-down resistor on the pin
{ MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ALT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ANALOG), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_ANALOG) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULLUP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULLDOWN) },
// legacy class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_OUT_PP), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_OUT_OD), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_PP), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_OD), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ANALOG), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_ANALOG) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(GPIO_NOPULL) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULLUP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULLDOWN) },
#include "genhdr/pins_af_const.h"
};
......@@ -553,6 +555,7 @@ const mp_obj_type_t pin_type = {
.name = MP_QSTR_Pin,
.print = pin_print,
.make_new = pin_make_new,
.call = pin_call,
.locals_dict = (mp_obj_t)&pin_locals_dict,
};
......
......@@ -144,6 +144,7 @@ Q(PinAF)
Q(PinNamed)
Q(init)
Q(value)
Q(alt)
Q(low)
Q(high)
Q(name)
......@@ -164,14 +165,18 @@ Q(pull)
Q(index)
Q(reg)
Q(IN)
Q(OUT)
Q(OPEN_DRAIN)
Q(ALT)
Q(ALT_OPEN_DRAIN)
Q(ANALOG)
Q(PULL_UP)
Q(PULL_DOWN)
Q(OUT_PP)
Q(OUT_OD)
Q(AF_PP)
Q(AF_OD)
Q(ANALOG)
Q(PULL_NONE)
Q(PULL_UP)
Q(PULL_DOWN)
// for LED object
Q(LED)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment