diff options
Diffstat (limited to 'stmhal/pin.c')
| -rw-r--r-- | stmhal/pin.c | 157 |
1 files changed, 105 insertions, 52 deletions
diff --git a/stmhal/pin.c b/stmhal/pin.c index f6c79d5d2..06923a492 100644 --- a/stmhal/pin.c +++ b/stmhal/pin.c @@ -12,54 +12,61 @@ #include "runtime.h" #include "pin.h" -// Usage Model: -// -// All Board Pins are predefined as pyb.Pin.board.Name -// -// x1_pin = pyb.Pin.board.X1 -// -// g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN) -// -// CPU pins which correspond to the board pins are available -// as pyb.cpu.Name. For the CPU pins, the names are the port letter -// followed by the pin number. On the PYBV4, pyb.Pin.board.X1 and -// pyb.Pin.cpu.B6 are the same pin. -// -// You can also use strings: -// -// g = pyb.Pin('X1', pyb.Pin.OUT_PP) -// -// Users can add their own names: -// -// pyb.Pin.dict["LeftMotorDir"] = pyb.Pin.cpu.C12 -// g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD) -// -// and can query mappings -// -// pin = pyb.Pin("LeftMotorDir") -// -// Users can also add their own mapping function: -// -// def MyMapper(pin_name): -// if pin_name == "LeftMotorDir": -// return pyb.Pin.cpu.A0 -// -// pyb.Pin.mapper(MyMapper) -// -// So, if you were to call: pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP) -// then "LeftMotorDir" is passed directly to the mapper function. -// -// To summarize, the following order determines how things get mapped into -// an ordinal pin number: -// -// 1 - Directly specify a pin object -// 2 - User supplied mapping function -// 3 - User supplied mapping (object must be usable as a dictionary key) -// 4 - Supply a string which matches a board pin -// 5 - Supply a string which matches a CPU port/pin -// -// You can set pyb.Pin.debug(True) to get some debug information about -// how a particular object gets mapped to a pin. +/// \moduleref pyb +/// \class Pin - control I/O pins +/// +/// A pin is the basic object to control I/O pins. It has methods to set +/// the mode of the pin (input, output, etc) and methods to get and set the +/// digital logic level. For analog control of a pin, see the ADC class. +/// +/// Usage Model: +/// +/// All Board Pins are predefined as pyb.Pin.board.Name +/// +/// x1_pin = pyb.Pin.board.X1 +/// +/// g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN) +/// +/// CPU pins which correspond to the board pins are available +/// as `pyb.cpu.Name`. For the CPU pins, the names are the port letter +/// followed by the pin number. On the PYBv1.0, `pyb.Pin.board.X1` and +/// `pyb.Pin.cpu.B6` are the same pin. +/// +/// You can also use strings: +/// +/// g = pyb.Pin('X1', pyb.Pin.OUT_PP) +/// +/// Users can add their own names: +/// +/// pyb.Pin.dict["LeftMotorDir"] = pyb.Pin.cpu.C12 +/// g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD) +/// +/// and can query mappings +/// +/// pin = pyb.Pin("LeftMotorDir") +/// +/// Users can also add their own mapping function: +/// +/// def MyMapper(pin_name): +/// if pin_name == "LeftMotorDir": +/// return pyb.Pin.cpu.A0 +/// +/// pyb.Pin.mapper(MyMapper) +/// +/// So, if you were to call: `pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP)` +/// then `"LeftMotorDir"` is passed directly to the mapper function. +/// +/// To summarise, the following order determines how things get mapped into +/// an ordinal pin number: +/// +/// 1. Directly specify a pin object +/// 2. User supplied mapping function +/// 3. User supplied mapping (object must be usable as a dictionary key) +/// 4. Supply a string which matches a board pin +/// 5. Supply a string which matches a CPU port/pin +/// +/// You can set `pyb.Pin.debug(True)` to get some debug information about +/// how a particular object gets mapped to a pin. // Pin class variables STATIC mp_obj_t pin_class_mapper; @@ -152,6 +159,8 @@ const pin_obj_t *pin_find(mp_obj_t user_obj) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", pin_name)); } +/// \method __str__() +/// Return a string describing the pin object. STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) { pin_obj_t *self = self_in; print(env, "<Pin %s>", self->name); @@ -159,7 +168,9 @@ STATIC void pin_print(void (*print)(void *env, const char *fmt, ...), void *env, STATIC mp_obj_t pin_obj_init(uint n_args, mp_obj_t *args); -// Pin constructor +/// \classmethod \constructor(id, ...) +/// Create a new Pin object associated with the id. If additional arguments are given, +/// they are used to initialise the pin. See `init`. STATIC mp_obj_t pin_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_obj_t *args) { mp_arg_check_num(n_args, n_kw, 1, 3, false); @@ -178,7 +189,8 @@ STATIC mp_obj_t pin_make_new(mp_obj_t self_in, uint n_args, uint n_kw, const mp_ return (mp_obj_t)pin; } -// class method +/// \classmethod mapper([fun]) +/// Get or set the pin mapper function. STATIC mp_obj_t pin_mapper(uint n_args, mp_obj_t *args) { if (n_args > 1) { pin_class_mapper = args[1]; @@ -189,7 +201,8 @@ STATIC mp_obj_t pin_mapper(uint n_args, mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_mapper_fun_obj, 1, 2, pin_mapper); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_mapper_obj, (mp_obj_t)&pin_mapper_fun_obj); -// class method +/// \classmethod dict([dict]) +/// Get or set the pin mapper dictionary. STATIC mp_obj_t pin_map_dict(uint n_args, mp_obj_t *args) { if (n_args > 1) { pin_class_map_dict = args[1]; @@ -200,7 +213,8 @@ STATIC mp_obj_t pin_map_dict(uint n_args, mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_map_dict_fun_obj, 1, 2, pin_map_dict); STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_map_dict_obj, (mp_obj_t)&pin_map_dict_fun_obj); -// class method +/// \classmethod debug([state]) +/// Get or set the debugging state (`True` or `False` for on or off). STATIC mp_obj_t pin_debug(uint n_args, mp_obj_t *args) { if (n_args > 1) { pin_class_debug = mp_obj_is_true(args[1]); @@ -211,6 +225,22 @@ STATIC mp_obj_t pin_debug(uint n_args, 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) +/// 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. +/// +/// Returns: `None`. STATIC mp_obj_t pin_obj_init(uint n_args, mp_obj_t *args) { pin_obj_t *self = args[0]; @@ -242,6 +272,13 @@ STATIC mp_obj_t pin_obj_init(uint n_args, mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_init_obj, 2, 3, pin_obj_init); +/// \method value([value]) +/// Get or set the digital logic level of the pin: +/// +/// - With no argument, return 0 or 1 depending on the logic level of the pin. +/// - With `value` given, set the logic level of the pin. `value` can be +/// 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(uint n_args, mp_obj_t *args) { pin_obj_t *self = args[0]; if (n_args == 1) { @@ -259,6 +296,8 @@ STATIC mp_obj_t pin_value(uint n_args, mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value); +/// \method low() +/// Set the pin to a low logic level. STATIC mp_obj_t pin_low(mp_obj_t self_in) { pin_obj_t *self = self_in; self->gpio->BSRRH = self->pin_mask; @@ -266,6 +305,8 @@ STATIC mp_obj_t pin_low(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_low_obj, pin_low); +/// \method high() +/// Set the pin to a high logic level. STATIC mp_obj_t pin_high(mp_obj_t self_in) { pin_obj_t *self = self_in; self->gpio->BSRRL = self->pin_mask; @@ -273,18 +314,24 @@ STATIC mp_obj_t pin_high(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_high_obj, pin_high); +/// \method name() +/// Get the pin name. STATIC mp_obj_t pin_name(mp_obj_t self_in) { pin_obj_t *self = self_in; return MP_OBJ_NEW_QSTR(qstr_from_str(self->name)); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_name_obj, pin_name); +/// \method port() +/// Get the pin port. STATIC mp_obj_t pin_port(mp_obj_t self_in) { pin_obj_t *self = self_in; return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self->port); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_port_obj, pin_port); +/// \method pin() +/// Get the pin number. STATIC mp_obj_t pin_pin(mp_obj_t self_in) { pin_obj_t *self = self_in; return MP_OBJ_NEW_SMALL_INT((mp_small_int_t)self->pin); @@ -311,6 +358,12 @@ STATIC const mp_map_elem_t pin_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj }, // 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 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_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) }, |
