aboutsummaryrefslogtreecommitdiff
path: root/stmhal/pin.c
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/pin.c')
-rw-r--r--stmhal/pin.c157
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) },