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.
This commit is contained in:
Damien George 2015-10-19 22:48:21 +01:00
parent bedab235f9
commit 2f96b1982a
3 changed files with 71 additions and 60 deletions

View File

@ -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 },

View File

@ -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,
};

View File

@ -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)