blob: e3ae0be400f33a657feb8736db5448f938199712 [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
Dave Hylandsf14b92b2014-03-12 18:06:26 -070027#include <stdio.h>
28#include <stdint.h>
29#include <string.h>
Dave Hylandsf14b92b2014-03-12 18:06:26 -070030
Damien George2cf6dfa2015-01-01 21:06:20 +000031#include "py/nlr.h"
32#include "py/runtime.h"
Damien George731f3592015-10-30 23:03:58 +000033#include "py/mphal.h"
Damien Georgeb68d98d2015-01-01 21:13:30 +000034#include "pin.h"
Dave Hylandsf14b92b2014-03-12 18:06:26 -070035
Damien George8d096402014-04-29 22:55:34 +010036/// \moduleref pyb
37/// \class Pin - control I/O pins
38///
39/// A pin is the basic object to control I/O pins. It has methods to set
40/// the mode of the pin (input, output, etc) and methods to get and set the
41/// digital logic level. For analog control of a pin, see the ADC class.
42///
43/// Usage Model:
44///
45/// All Board Pins are predefined as pyb.Pin.board.Name
46///
47/// x1_pin = pyb.Pin.board.X1
48///
49/// g = pyb.Pin(pyb.Pin.board.X1, pyb.Pin.IN)
50///
51/// CPU pins which correspond to the board pins are available
52/// as `pyb.cpu.Name`. For the CPU pins, the names are the port letter
53/// followed by the pin number. On the PYBv1.0, `pyb.Pin.board.X1` and
54/// `pyb.Pin.cpu.B6` are the same pin.
55///
56/// You can also use strings:
57///
58/// g = pyb.Pin('X1', pyb.Pin.OUT_PP)
59///
60/// Users can add their own names:
61///
Dave Hylands6f418fc2014-07-22 07:57:36 -070062/// MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 }
63/// pyb.Pin.dict(MyMapperDict)
Damien George8d096402014-04-29 22:55:34 +010064/// g = pyb.Pin("LeftMotorDir", pyb.Pin.OUT_OD)
65///
66/// and can query mappings
67///
68/// pin = pyb.Pin("LeftMotorDir")
69///
70/// Users can also add their own mapping function:
71///
72/// def MyMapper(pin_name):
73/// if pin_name == "LeftMotorDir":
74/// return pyb.Pin.cpu.A0
75///
76/// pyb.Pin.mapper(MyMapper)
77///
78/// So, if you were to call: `pyb.Pin("LeftMotorDir", pyb.Pin.OUT_PP)`
79/// then `"LeftMotorDir"` is passed directly to the mapper function.
80///
81/// To summarise, the following order determines how things get mapped into
82/// an ordinal pin number:
83///
84/// 1. Directly specify a pin object
85/// 2. User supplied mapping function
86/// 3. User supplied mapping (object must be usable as a dictionary key)
87/// 4. Supply a string which matches a board pin
88/// 5. Supply a string which matches a CPU port/pin
89///
90/// You can set `pyb.Pin.debug(True)` to get some debug information about
91/// how a particular object gets mapped to a pin.
Damien Georgec66d86c2014-04-18 22:38:09 +010092
93// Pin class variables
Damien Georgec66d86c2014-04-18 22:38:09 +010094STATIC bool pin_class_debug;
95
Damien Georgeccacdf42014-08-04 11:09:51 +010096void pin_init0(void) {
Damien George3b51b3e2015-01-07 23:38:50 +000097 MP_STATE_PORT(pin_class_mapper) = mp_const_none;
98 MP_STATE_PORT(pin_class_map_dict) = mp_const_none;
Damien Georgec66d86c2014-04-18 22:38:09 +010099 pin_class_debug = false;
100}
101
102// C API used to convert a user-supplied pin name into an ordinal pin number.
103const pin_obj_t *pin_find(mp_obj_t user_obj) {
104 const pin_obj_t *pin_obj;
105
106 // If a pin was provided, then use it
107 if (MP_OBJ_IS_TYPE(user_obj, &pin_type)) {
108 pin_obj = user_obj;
109 if (pin_class_debug) {
110 printf("Pin map passed pin ");
111 mp_obj_print((mp_obj_t)pin_obj, PRINT_STR);
112 printf("\n");
113 }
114 return pin_obj;
115 }
116
Damien George3b51b3e2015-01-07 23:38:50 +0000117 if (MP_STATE_PORT(pin_class_mapper) != mp_const_none) {
118 pin_obj = mp_call_function_1(MP_STATE_PORT(pin_class_mapper), user_obj);
Damien Georgec66d86c2014-04-18 22:38:09 +0100119 if (pin_obj != mp_const_none) {
120 if (!MP_OBJ_IS_TYPE(pin_obj, &pin_type)) {
121 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin.mapper didn't return a Pin object"));
122 }
123 if (pin_class_debug) {
124 printf("Pin.mapper maps ");
125 mp_obj_print(user_obj, PRINT_REPR);
126 printf(" to ");
127 mp_obj_print((mp_obj_t)pin_obj, PRINT_STR);
128 printf("\n");
129 }
130 return pin_obj;
131 }
132 // The pin mapping function returned mp_const_none, fall through to
133 // other lookup methods.
134 }
135
Damien George3b51b3e2015-01-07 23:38:50 +0000136 if (MP_STATE_PORT(pin_class_map_dict) != mp_const_none) {
137 mp_map_t *pin_map_map = mp_obj_dict_get_map(MP_STATE_PORT(pin_class_map_dict));
Damien Georgec66d86c2014-04-18 22:38:09 +0100138 mp_map_elem_t *elem = mp_map_lookup(pin_map_map, user_obj, MP_MAP_LOOKUP);
139 if (elem != NULL && elem->value != NULL) {
140 pin_obj = elem->value;
141 if (pin_class_debug) {
142 printf("Pin.map_dict maps ");
143 mp_obj_print(user_obj, PRINT_REPR);
144 printf(" to ");
145 mp_obj_print((mp_obj_t)pin_obj, PRINT_STR);
146 printf("\n");
147 }
148 return pin_obj;
149 }
150 }
151
152 // See if the pin name matches a board pin
Dave Hylands6f418fc2014-07-22 07:57:36 -0700153 pin_obj = pin_find_named_pin(&pin_board_pins_locals_dict, user_obj);
Damien Georgec66d86c2014-04-18 22:38:09 +0100154 if (pin_obj) {
155 if (pin_class_debug) {
156 printf("Pin.board maps ");
157 mp_obj_print(user_obj, PRINT_REPR);
158 printf(" to ");
159 mp_obj_print((mp_obj_t)pin_obj, PRINT_STR);
160 printf("\n");
161 }
162 return pin_obj;
163 }
164
165 // See if the pin name matches a cpu pin
Dave Hylands6f418fc2014-07-22 07:57:36 -0700166 pin_obj = pin_find_named_pin(&pin_cpu_pins_locals_dict, user_obj);
Damien Georgec66d86c2014-04-18 22:38:09 +0100167 if (pin_obj) {
168 if (pin_class_debug) {
169 printf("Pin.cpu maps ");
170 mp_obj_print(user_obj, PRINT_REPR);
171 printf(" to ");
172 mp_obj_print((mp_obj_t)pin_obj, PRINT_STR);
173 printf("\n");
174 }
175 return pin_obj;
176 }
177
Dave Hylands6f418fc2014-07-22 07:57:36 -0700178 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin '%s' not a valid pin identifier", mp_obj_str_get_str(user_obj)));
Damien Georgec66d86c2014-04-18 22:38:09 +0100179}
180
Damien George8d096402014-04-29 22:55:34 +0100181/// \method __str__()
182/// Return a string describing the pin object.
Damien George7f9d1d62015-04-09 23:56:15 +0100183STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700184 pin_obj_t *self = self_in;
Dave Hylands6f418fc2014-07-22 07:57:36 -0700185
Damien George2605df32014-08-09 09:19:37 +0100186 // pin name
blmorris4c459212015-04-16 13:40:06 -0400187 mp_printf(print, "Pin(Pin.cpu.%q, mode=Pin.", self->name);
Dave Hylands6f418fc2014-07-22 07:57:36 -0700188
Dave Hylands6f418fc2014-07-22 07:57:36 -0700189 uint32_t mode = pin_get_mode(self);
Damien George2605df32014-08-09 09:19:37 +0100190
Dave Hylands6f418fc2014-07-22 07:57:36 -0700191 if (mode == GPIO_MODE_ANALOG) {
Damien George2605df32014-08-09 09:19:37 +0100192 // analog
Damien George7f9d1d62015-04-09 23:56:15 +0100193 mp_print_str(print, "ANALOG)");
Damien George2605df32014-08-09 09:19:37 +0100194
Dave Hylands6f418fc2014-07-22 07:57:36 -0700195 } else {
Damien George2605df32014-08-09 09:19:37 +0100196 // IO mode
197 bool af = false;
198 qstr mode_qst;
199 if (mode == GPIO_MODE_INPUT) {
200 mode_qst = MP_QSTR_IN;
201 } else if (mode == GPIO_MODE_OUTPUT_PP) {
202 mode_qst = MP_QSTR_OUT_PP;
203 } else if (mode == GPIO_MODE_OUTPUT_OD) {
204 mode_qst = MP_QSTR_OUT_OD;
205 } else {
206 af = true;
207 if (mode == GPIO_MODE_AF_PP) {
208 mode_qst = MP_QSTR_AF_PP;
209 } else {
210 mode_qst = MP_QSTR_AF_OD;
211 }
212 }
Damien George7f9d1d62015-04-09 23:56:15 +0100213 mp_print_str(print, qstr_str(mode_qst));
Damien George2605df32014-08-09 09:19:37 +0100214
215 // pull mode
216 qstr pull_qst = MP_QSTR_NULL;
Dave Hylands6f418fc2014-07-22 07:57:36 -0700217 uint32_t pull = pin_get_pull(self);
218 if (pull == GPIO_PULLUP) {
Damien George2605df32014-08-09 09:19:37 +0100219 pull_qst = MP_QSTR_PULL_UP;
Dave Hylands6f418fc2014-07-22 07:57:36 -0700220 } else if (pull == GPIO_PULLDOWN) {
Damien George2605df32014-08-09 09:19:37 +0100221 pull_qst = MP_QSTR_PULL_DOWN;
Dave Hylands6f418fc2014-07-22 07:57:36 -0700222 }
Damien George2605df32014-08-09 09:19:37 +0100223 if (pull_qst != MP_QSTR_NULL) {
blmorris4c459212015-04-16 13:40:06 -0400224 mp_printf(print, ", pull=Pin.%q", pull_qst);
Damien George2605df32014-08-09 09:19:37 +0100225 }
226
227 // AF mode
228 if (af) {
229 mp_uint_t af_idx = pin_get_af(self);
230 const pin_af_obj_t *af_obj = pin_find_af_by_index(self, af_idx);
231 if (af_obj == NULL) {
Damien George7f9d1d62015-04-09 23:56:15 +0100232 mp_printf(print, ", af=%d)", af_idx);
Dave Hylands6f418fc2014-07-22 07:57:36 -0700233 } else {
blmorris4c459212015-04-16 13:40:06 -0400234 mp_printf(print, ", af=Pin.%q)", af_obj->name);
Dave Hylands6f418fc2014-07-22 07:57:36 -0700235 }
236 } else {
Damien George7f9d1d62015-04-09 23:56:15 +0100237 mp_print_str(print, ")");
Dave Hylands6f418fc2014-07-22 07:57:36 -0700238 }
239 }
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700240}
241
Damien Georgeecc88e92014-08-30 00:35:11 +0100242STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *pin, mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args);
Damien George3d191372014-04-19 02:17:57 +0100243
Damien George8d096402014-04-29 22:55:34 +0100244/// \classmethod \constructor(id, ...)
245/// Create a new Pin object associated with the id. If additional arguments are given,
246/// they are used to initialise the pin. See `init`.
Damien George5b3f0b72016-01-03 15:55:55 +0000247STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
Dave Hylands6f418fc2014-07-22 07:57:36 -0700248 mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
Damien Georgec66d86c2014-04-18 22:38:09 +0100249
250 // Run an argument through the mapper and return the result.
251 const pin_obj_t *pin = pin_find(args[0]);
252
Dave Hylands6f418fc2014-07-22 07:57:36 -0700253 if (n_args > 1 || n_kw > 0) {
Damien Georgec66d86c2014-04-18 22:38:09 +0100254 // pin mode given, so configure this GPIO
Dave Hylands6f418fc2014-07-22 07:57:36 -0700255 mp_map_t kw_args;
256 mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
257 pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
Damien Georgec66d86c2014-04-18 22:38:09 +0100258 }
259
260 return (mp_obj_t)pin;
261}
262
Damien George2f96b192015-10-19 22:48:21 +0100263// fast method for getting/setting pin value
264STATIC 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) {
265 mp_arg_check_num(n_args, n_kw, 0, 1, false);
266 pin_obj_t *self = self_in;
267 if (n_args == 0) {
268 // get pin
269 return MP_OBJ_NEW_SMALL_INT(GPIO_read_pin(self->gpio, self->pin));
270 } else {
271 // set pin
272 if (mp_obj_is_true(args[0])) {
273 GPIO_set_pin(self->gpio, self->pin_mask);
274 } else {
275 GPIO_clear_pin(self->gpio, self->pin_mask);
276 }
277 return mp_const_none;
278 }
279}
280
Damien George8d096402014-04-29 22:55:34 +0100281/// \classmethod mapper([fun])
282/// Get or set the pin mapper function.
Damien Georgeecc88e92014-08-30 00:35:11 +0100283STATIC mp_obj_t pin_mapper(mp_uint_t n_args, const mp_obj_t *args) {
Damien Georgec66d86c2014-04-18 22:38:09 +0100284 if (n_args > 1) {
Damien George3b51b3e2015-01-07 23:38:50 +0000285 MP_STATE_PORT(pin_class_mapper) = args[1];
Damien Georgec66d86c2014-04-18 22:38:09 +0100286 return mp_const_none;
287 }
Damien George3b51b3e2015-01-07 23:38:50 +0000288 return MP_STATE_PORT(pin_class_mapper);
Damien Georgec66d86c2014-04-18 22:38:09 +0100289}
290STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_mapper_fun_obj, 1, 2, pin_mapper);
291STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_mapper_obj, (mp_obj_t)&pin_mapper_fun_obj);
292
Damien George8d096402014-04-29 22:55:34 +0100293/// \classmethod dict([dict])
294/// Get or set the pin mapper dictionary.
Damien Georgeecc88e92014-08-30 00:35:11 +0100295STATIC mp_obj_t pin_map_dict(mp_uint_t n_args, const mp_obj_t *args) {
Damien Georgec66d86c2014-04-18 22:38:09 +0100296 if (n_args > 1) {
Damien George3b51b3e2015-01-07 23:38:50 +0000297 MP_STATE_PORT(pin_class_map_dict) = args[1];
Damien Georgec66d86c2014-04-18 22:38:09 +0100298 return mp_const_none;
299 }
Damien George3b51b3e2015-01-07 23:38:50 +0000300 return MP_STATE_PORT(pin_class_map_dict);
Damien Georgec66d86c2014-04-18 22:38:09 +0100301}
302STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_map_dict_fun_obj, 1, 2, pin_map_dict);
303STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_map_dict_obj, (mp_obj_t)&pin_map_dict_fun_obj);
304
Damien George4b674632014-08-08 22:26:53 +0100305/// \classmethod af_list()
Dave Hylands6f418fc2014-07-22 07:57:36 -0700306/// Returns an array of alternate functions available for this pin.
307STATIC mp_obj_t pin_af_list(mp_obj_t self_in) {
308 pin_obj_t *self = self_in;
309 mp_obj_t result = mp_obj_new_list(0, NULL);
310
311 const pin_af_obj_t *af = self->af;
312 for (mp_uint_t i = 0; i < self->num_af; i++, af++) {
313 mp_obj_list_append(result, (mp_obj_t)af);
314 }
315 return result;
316}
317STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_list_obj, pin_af_list);
318
Damien George8d096402014-04-29 22:55:34 +0100319/// \classmethod debug([state])
320/// Get or set the debugging state (`True` or `False` for on or off).
Damien Georgeecc88e92014-08-30 00:35:11 +0100321STATIC mp_obj_t pin_debug(mp_uint_t n_args, const mp_obj_t *args) {
Damien Georgec66d86c2014-04-18 22:38:09 +0100322 if (n_args > 1) {
323 pin_class_debug = mp_obj_is_true(args[1]);
324 return mp_const_none;
325 }
Paul Sokolovsky1b586f32015-10-11 12:09:43 +0300326 return mp_obj_new_bool(pin_class_debug);
Damien Georgec66d86c2014-04-18 22:38:09 +0100327}
328STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_debug_fun_obj, 1, 2, pin_debug);
329STATIC MP_DEFINE_CONST_CLASSMETHOD_OBJ(pin_debug_obj, (mp_obj_t)&pin_debug_fun_obj);
330
Damien George2f96b192015-10-19 22:48:21 +0100331// init(mode, pull=None, af=-1, *, value, alt)
332STATIC 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) {
333 static const mp_arg_t allowed_args[] = {
334 { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
335 { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
336 { MP_QSTR_af, MP_ARG_INT, {.u_int = -1}}, // legacy
337 { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
338 { MP_QSTR_alt, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1}},
339 };
Dave Hylands6f418fc2014-07-22 07:57:36 -0700340
Dave Hylands6f418fc2014-07-22 07:57:36 -0700341 // parse args
Damien George2f96b192015-10-19 22:48:21 +0100342 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
343 mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
Damien George3d191372014-04-19 02:17:57 +0100344
345 // get io mode
Damien George2f96b192015-10-19 22:48:21 +0100346 uint mode = args[0].u_int;
Damien George3d191372014-04-19 02:17:57 +0100347 if (!IS_GPIO_MODE(mode)) {
348 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin mode: %d", mode));
349 }
350
351 // get pull mode
Damien George2f96b192015-10-19 22:48:21 +0100352 uint pull = GPIO_NOPULL;
353 if (args[1].u_obj != mp_const_none) {
354 pull = mp_obj_get_int(args[1].u_obj);
355 }
Dave Hylands6f418fc2014-07-22 07:57:36 -0700356 if (!IS_GPIO_PULL(pull)) {
357 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin pull: %d", pull));
358 }
359
Damien George2f96b192015-10-19 22:48:21 +0100360 // get af (alternate function); alt-arg overrides af-arg
361 mp_int_t af = args[4].u_int;
362 if (af == -1) {
363 af = args[2].u_int;
364 }
Damien George04019e32014-08-09 08:51:12 +0100365 if ((mode == GPIO_MODE_AF_PP || mode == GPIO_MODE_AF_OD) && !IS_GPIO_AF(af)) {
366 nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin af: %d", af));
Dave Hylands6f418fc2014-07-22 07:57:36 -0700367 }
Damien George3d191372014-04-19 02:17:57 +0100368
Damien George95ea4f02014-08-06 16:04:57 +0100369 // enable the peripheral clock for the port of this pin
Damien George08517512015-08-03 00:05:16 +0100370 mp_hal_gpio_clock_enable(self->gpio);
Damien George95ea4f02014-08-06 16:04:57 +0100371
Damien George2f96b192015-10-19 22:48:21 +0100372 // if given, set the pin value before initialising to prevent glitches
373 if (args[3].u_obj != MP_OBJ_NULL) {
374 if (mp_obj_is_true(args[3].u_obj)) {
375 GPIO_set_pin(self->gpio, self->pin_mask);
376 } else {
377 GPIO_clear_pin(self->gpio, self->pin_mask);
378 }
379 }
380
Damien George3d191372014-04-19 02:17:57 +0100381 // configure the GPIO as requested
382 GPIO_InitTypeDef GPIO_InitStructure;
383 GPIO_InitStructure.Pin = self->pin_mask;
384 GPIO_InitStructure.Mode = mode;
385 GPIO_InitStructure.Pull = pull;
386 GPIO_InitStructure.Speed = GPIO_SPEED_FAST;
Damien George04019e32014-08-09 08:51:12 +0100387 GPIO_InitStructure.Alternate = af;
Damien George3d191372014-04-19 02:17:57 +0100388 HAL_GPIO_Init(self->gpio, &GPIO_InitStructure);
389
390 return mp_const_none;
391}
Damien George4b674632014-08-08 22:26:53 +0100392
Damien Georgeecc88e92014-08-30 00:35:11 +0100393STATIC mp_obj_t pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
Dave Hylands6f418fc2014-07-22 07:57:36 -0700394 return pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
395}
Dave Hylandsbecbc872014-08-20 13:21:11 -0700396MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, pin_obj_init);
Damien George3d191372014-04-19 02:17:57 +0100397
Damien George8d096402014-04-29 22:55:34 +0100398/// \method value([value])
399/// Get or set the digital logic level of the pin:
400///
401/// - With no argument, return 0 or 1 depending on the logic level of the pin.
402/// - With `value` given, set the logic level of the pin. `value` can be
403/// anything that converts to a boolean. If it converts to `True`, the pin
404/// is set high, otherwise it is set low.
Damien Georgeecc88e92014-08-30 00:35:11 +0100405STATIC mp_obj_t pin_value(mp_uint_t n_args, const mp_obj_t *args) {
Damien George2f96b192015-10-19 22:48:21 +0100406 return pin_call(args[0], n_args - 1, 0, args + 1);
Damien Georgec66d86c2014-04-18 22:38:09 +0100407}
408STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value);
409
Damien George8d096402014-04-29 22:55:34 +0100410/// \method low()
411/// Set the pin to a low logic level.
Damien Georgec66d86c2014-04-18 22:38:09 +0100412STATIC mp_obj_t pin_low(mp_obj_t self_in) {
413 pin_obj_t *self = self_in;
Dave Hylands4f1b7fe2014-06-15 22:33:14 -0700414 GPIO_clear_pin(self->gpio, self->pin_mask);;
Damien Georgec66d86c2014-04-18 22:38:09 +0100415 return mp_const_none;
416}
417STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_low_obj, pin_low);
418
Damien George8d096402014-04-29 22:55:34 +0100419/// \method high()
420/// Set the pin to a high logic level.
Damien Georgec66d86c2014-04-18 22:38:09 +0100421STATIC mp_obj_t pin_high(mp_obj_t self_in) {
422 pin_obj_t *self = self_in;
Dave Hylands4f1b7fe2014-06-15 22:33:14 -0700423 GPIO_set_pin(self->gpio, self->pin_mask);;
Damien Georgec66d86c2014-04-18 22:38:09 +0100424 return mp_const_none;
425}
426STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_high_obj, pin_high);
427
Damien George8d096402014-04-29 22:55:34 +0100428/// \method name()
429/// Get the pin name.
Damien Georgec66d86c2014-04-18 22:38:09 +0100430STATIC mp_obj_t pin_name(mp_obj_t self_in) {
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700431 pin_obj_t *self = self_in;
Dave Hylands6f418fc2014-07-22 07:57:36 -0700432 return MP_OBJ_NEW_QSTR(self->name);
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700433}
Damien Georgec66d86c2014-04-18 22:38:09 +0100434STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_name_obj, pin_name);
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700435
Dave Hylands6f418fc2014-07-22 07:57:36 -0700436/// \method names()
437/// Returns the cpu and board names for this pin.
438STATIC mp_obj_t pin_names(mp_obj_t self_in) {
439 pin_obj_t *self = self_in;
440 mp_obj_t result = mp_obj_new_list(0, NULL);
441 mp_obj_list_append(result, MP_OBJ_NEW_QSTR(self->name));
442
443 mp_map_t *map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict);
444 mp_map_elem_t *elem = map->table;
445
446 for (mp_uint_t i = 0; i < map->used; i++, elem++) {
447 if (elem->value == self) {
448 mp_obj_list_append(result, elem->key);
449 }
450 }
451 return result;
452}
453STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_names_obj, pin_names);
454
Damien George8d096402014-04-29 22:55:34 +0100455/// \method port()
456/// Get the pin port.
Damien Georgec66d86c2014-04-18 22:38:09 +0100457STATIC mp_obj_t pin_port(mp_obj_t self_in) {
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700458 pin_obj_t *self = self_in;
Damien Georgebb4c6f32014-07-31 10:49:14 +0100459 return MP_OBJ_NEW_SMALL_INT(self->port);
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700460}
Damien Georgec66d86c2014-04-18 22:38:09 +0100461STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_port_obj, pin_port);
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700462
Damien George8d096402014-04-29 22:55:34 +0100463/// \method pin()
464/// Get the pin number.
Damien Georgec66d86c2014-04-18 22:38:09 +0100465STATIC mp_obj_t pin_pin(mp_obj_t self_in) {
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700466 pin_obj_t *self = self_in;
Damien Georgebb4c6f32014-07-31 10:49:14 +0100467 return MP_OBJ_NEW_SMALL_INT(self->pin);
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700468}
Damien Georgec66d86c2014-04-18 22:38:09 +0100469STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pin_obj, pin_pin);
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700470
Dave Hylands6f418fc2014-07-22 07:57:36 -0700471/// \method gpio()
472/// Returns the base address of the GPIO block associated with this pin.
473STATIC mp_obj_t pin_gpio(mp_obj_t self_in) {
474 pin_obj_t *self = self_in;
475 return MP_OBJ_NEW_SMALL_INT((mp_int_t)self->gpio);
476}
477STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_gpio_obj, pin_gpio);
478
Dave Hylands3d945552014-08-10 23:18:10 -0700479/// \method mode()
480/// Returns the currently configured mode of the pin. The integer returned
481/// will match one of the allowed constants for the mode argument to the init
482/// function.
483STATIC mp_obj_t pin_mode(mp_obj_t self_in) {
484 return MP_OBJ_NEW_SMALL_INT(pin_get_mode(self_in));
485}
486STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_mode_obj, pin_mode);
487
488/// \method pull()
489/// Returns the currently configured pull of the pin. The integer returned
490/// will match one of the allowed constants for the pull argument to the init
491/// function.
492STATIC mp_obj_t pin_pull(mp_obj_t self_in) {
493 return MP_OBJ_NEW_SMALL_INT(pin_get_pull(self_in));
494}
495STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pull_obj, pin_pull);
496
497/// \method af()
Damien George2c4e67e2014-08-24 18:30:22 +0100498/// Returns the currently configured alternate-function of the pin. The
499/// integer returned will match one of the allowed constants for the af
500/// argument to the init function.
Dave Hylands3d945552014-08-10 23:18:10 -0700501STATIC mp_obj_t pin_af(mp_obj_t self_in) {
502 return MP_OBJ_NEW_SMALL_INT(pin_get_af(self_in));
503}
504STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_obj, pin_af);
505
Damien Georgec66d86c2014-04-18 22:38:09 +0100506STATIC const mp_map_elem_t pin_locals_dict_table[] = {
507 // instance methods
Damien George3d191372014-04-19 02:17:57 +0100508 { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pin_init_obj },
Damien Georgec66d86c2014-04-18 22:38:09 +0100509 { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pin_value_obj },
510 { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pin_low_obj },
511 { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pin_high_obj },
512 { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_name_obj },
Dave Hylands6f418fc2014-07-22 07:57:36 -0700513 { MP_OBJ_NEW_QSTR(MP_QSTR_names), (mp_obj_t)&pin_names_obj },
514 { MP_OBJ_NEW_QSTR(MP_QSTR_af_list), (mp_obj_t)&pin_af_list_obj },
Damien Georgec66d86c2014-04-18 22:38:09 +0100515 { MP_OBJ_NEW_QSTR(MP_QSTR_port), (mp_obj_t)&pin_port_obj },
516 { MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&pin_pin_obj },
Dave Hylands6f418fc2014-07-22 07:57:36 -0700517 { MP_OBJ_NEW_QSTR(MP_QSTR_gpio), (mp_obj_t)&pin_gpio_obj },
Dave Hylands3d945552014-08-10 23:18:10 -0700518 { MP_OBJ_NEW_QSTR(MP_QSTR_mode), (mp_obj_t)&pin_mode_obj },
519 { MP_OBJ_NEW_QSTR(MP_QSTR_pull), (mp_obj_t)&pin_pull_obj },
520 { MP_OBJ_NEW_QSTR(MP_QSTR_af), (mp_obj_t)&pin_af_obj },
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700521
Damien Georgec66d86c2014-04-18 22:38:09 +0100522 // class methods
523 { MP_OBJ_NEW_QSTR(MP_QSTR_mapper), (mp_obj_t)&pin_mapper_obj },
524 { MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&pin_map_dict_obj },
525 { MP_OBJ_NEW_QSTR(MP_QSTR_debug), (mp_obj_t)&pin_debug_obj },
526
527 // class attributes
Dave Hylands6f418fc2014-07-22 07:57:36 -0700528 { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&pin_board_pins_obj_type },
529 { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type },
Damien Georgec66d86c2014-04-18 22:38:09 +0100530
531 // class constants
532 { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) },
Damien George2f96b192015-10-19 22:48:21 +0100533 { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) },
534 { MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) },
535 { MP_OBJ_NEW_QSTR(MP_QSTR_ALT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) },
536 { MP_OBJ_NEW_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) },
537 { MP_OBJ_NEW_QSTR(MP_QSTR_ANALOG), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_ANALOG) },
538 { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULLUP) },
539 { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULLDOWN) },
540
541 // legacy class constants
Damien Georgec66d86c2014-04-18 22:38:09 +0100542 { MP_OBJ_NEW_QSTR(MP_QSTR_OUT_PP), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) },
543 { MP_OBJ_NEW_QSTR(MP_QSTR_OUT_OD), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) },
544 { MP_OBJ_NEW_QSTR(MP_QSTR_AF_PP), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) },
545 { MP_OBJ_NEW_QSTR(MP_QSTR_AF_OD), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) },
Damien Georgec66d86c2014-04-18 22:38:09 +0100546 { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(GPIO_NOPULL) },
Damien George4b674632014-08-08 22:26:53 +0100547
Damien George284efa82014-08-08 22:34:06 +0100548#include "genhdr/pins_af_const.h"
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700549};
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700550
Damien Georgec66d86c2014-04-18 22:38:09 +0100551STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table);
552
553const mp_obj_type_t pin_type = {
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700554 { &mp_type_type },
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700555 .name = MP_QSTR_Pin,
Damien Georgec66d86c2014-04-18 22:38:09 +0100556 .print = pin_print,
557 .make_new = pin_make_new,
Damien George2f96b192015-10-19 22:48:21 +0100558 .call = pin_call,
Damien Georgec66d86c2014-04-18 22:38:09 +0100559 .locals_dict = (mp_obj_t)&pin_locals_dict,
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700560};
561
Dave Hylands6f418fc2014-07-22 07:57:36 -0700562/// \moduleref pyb
563/// \class PinAF - Pin Alternate Functions
564///
565/// A Pin represents a physical pin on the microcprocessor. Each pin
566/// can have a variety of functions (GPIO, I2C SDA, etc). Each PinAF
567/// object represents a particular function for a pin.
568///
569/// Usage Model:
570///
571/// x3 = pyb.Pin.board.X3
572/// x3_af = x3.af_list()
573///
574/// x3_af will now contain an array of PinAF objects which are availble on
575/// pin X3.
576///
577/// For the pyboard, x3_af would contain:
578/// [Pin.AF1_TIM2, Pin.AF2_TIM5, Pin.AF3_TIM9, Pin.AF7_USART2]
579///
580/// Normally, each peripheral would configure the af automatically, but sometimes
581/// the same function is available on multiple pins, and having more control
582/// is desired.
583///
584/// To configure X3 to expose TIM2_CH3, you could use:
585/// pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=pyb.Pin.AF1_TIM2)
586/// or:
587/// pin = pyb.Pin(pyb.Pin.board.X3, mode=pyb.Pin.AF_PP, af=1)
588
589/// \method __str__()
590/// Return a string describing the alternate function.
Damien George7f9d1d62015-04-09 23:56:15 +0100591STATIC void pin_af_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700592 pin_af_obj_t *self = self_in;
blmorris4c459212015-04-16 13:40:06 -0400593 mp_printf(print, "Pin.%q", self->name);
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700594}
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700595
Dave Hylands6f418fc2014-07-22 07:57:36 -0700596/// \method index()
597/// Return the alternate function index.
598STATIC mp_obj_t pin_af_index(mp_obj_t self_in) {
599 pin_af_obj_t *af = self_in;
600 return MP_OBJ_NEW_SMALL_INT(af->idx);
601}
602STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_index_obj, pin_af_index);
603
Damien Georgeea439e52014-08-08 23:30:01 +0100604/// \method name()
Dave Hylands6f418fc2014-07-22 07:57:36 -0700605/// Return the name of the alternate function.
606STATIC mp_obj_t pin_af_name(mp_obj_t self_in) {
607 pin_af_obj_t *af = self_in;
608 return MP_OBJ_NEW_QSTR(af->name);
609}
610STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_name_obj, pin_af_name);
611
Damien Georgeea439e52014-08-08 23:30:01 +0100612/// \method reg()
Dave Hylands6f418fc2014-07-22 07:57:36 -0700613/// Return the base register associated with the peripheral assigned to this
614/// alternate function. For example, if the alternate function were TIM2_CH3
615/// this would return stm.TIM2
616STATIC mp_obj_t pin_af_reg(mp_obj_t self_in) {
617 pin_af_obj_t *af = self_in;
618 return MP_OBJ_NEW_SMALL_INT((mp_uint_t)af->reg);
619}
620STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_reg_obj, pin_af_reg);
621
622STATIC const mp_map_elem_t pin_af_locals_dict_table[] = {
623 { MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&pin_af_index_obj },
624 { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_af_name_obj },
625 { MP_OBJ_NEW_QSTR(MP_QSTR_reg), (mp_obj_t)&pin_af_reg_obj },
626};
627STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table);
628
Damien Georgec66d86c2014-04-18 22:38:09 +0100629const mp_obj_type_t pin_af_type = {
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700630 { &mp_type_type },
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700631 .name = MP_QSTR_PinAF,
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700632 .print = pin_af_obj_print,
Dave Hylands6f418fc2014-07-22 07:57:36 -0700633 .locals_dict = (mp_obj_t)&pin_af_locals_dict,
Dave Hylandsf14b92b2014-03-12 18:06:26 -0700634};