From 2f96b1982a84b21788756d9220b5c4ead657e8f7 Mon Sep 17 00:00:00 2001 From: Damien George Date: Mon, 19 Oct 2015 22:48:21 +0100 Subject: [PATCH] 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. --- stmhal/modmachine.c | 5 +- stmhal/pin.c | 115 ++++++++++++++++++++++-------------------- stmhal/qstrdefsport.h | 11 ++-- 3 files changed, 71 insertions(+), 60 deletions(-) diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c index 0d6ada635c..b452e223ec 100644 --- a/stmhal/modmachine.c +++ b/stmhal/modmachine.c @@ -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 }, diff --git a/stmhal/pin.c b/stmhal/pin.c index 9f40b11d67..3aba949759 100644 --- a/stmhal/pin.c +++ b/stmhal/pin.c @@ -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, }; diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index 94e9b6440a..e2eabe3a3f 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -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)