blob: a1e94e898eef3d574daca9c6ab58ce263ac8dc7c [file] [log] [blame]
Damien George87c62502015-02-13 22:21:44 +00001/*
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, 2015 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
27#include <stdio.h>
28#include <stdint.h>
29#include <string.h>
30
Damien George674bf1b2016-04-14 11:15:43 +010031#include "etshal.h"
Damien George87c62502015-02-13 22:21:44 +000032#include "c_types.h"
33#include "user_interface.h"
34#include "gpio.h"
35
36#include "py/nlr.h"
37#include "py/runtime.h"
Damien George674bf1b2016-04-14 11:15:43 +010038#include "py/gc.h"
Damien George68e222a2016-05-26 15:42:27 +010039#include "py/mphal.h"
Paul Sokolovsky18b68352017-01-01 19:02:28 +030040#include "extmod/virtpin.h"
Paul Sokolovsky8bc3fc22016-11-06 01:30:19 +030041#include "modmachine.h"
Damien George674bf1b2016-04-14 11:15:43 +010042
43#define GET_TRIGGER(phys_port) \
44 GPIO_PIN_INT_TYPE_GET(GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)))
45#define SET_TRIGGER(phys_port, trig) \
46 (GPIO_REG_WRITE(GPIO_PIN_ADDR(phys_port), \
47 (GPIO_REG_READ(GPIO_PIN_ADDR(phys_port)) & ~GPIO_PIN_INT_TYPE_MASK) \
48 | GPIO_PIN_INT_TYPE_SET(trig))) \
Damien George87c62502015-02-13 22:21:44 +000049
50#define GPIO_MODE_INPUT (0)
51#define GPIO_MODE_OUTPUT (1)
Damien Georgecdad2b62015-12-28 17:42:20 +000052#define GPIO_MODE_OPEN_DRAIN (2) // synthesised
Damien George87c62502015-02-13 22:21:44 +000053#define GPIO_PULL_NONE (0)
54#define GPIO_PULL_UP (1)
Josef Gajdusek7d8edef2015-05-26 18:54:55 +020055// Removed in SDK 1.1.0
56//#define GPIO_PULL_DOWN (2)
Damien George87c62502015-02-13 22:21:44 +000057
Damien George674bf1b2016-04-14 11:15:43 +010058typedef struct _pin_irq_obj_t {
59 mp_obj_base_t base;
60 uint16_t phys_port;
61} pin_irq_obj_t;
62
Damien Georgea2d5d842016-04-22 10:04:12 +010063const pyb_pin_obj_t pyb_pin_obj[16 + 1] = {
Damien Georgea9a732a2016-04-13 22:38:44 +010064 {{&pyb_pin_type}, 0, FUNC_GPIO0, PERIPHS_IO_MUX_GPIO0_U},
65 {{&pyb_pin_type}, 1, FUNC_GPIO1, PERIPHS_IO_MUX_U0TXD_U},
66 {{&pyb_pin_type}, 2, FUNC_GPIO2, PERIPHS_IO_MUX_GPIO2_U},
67 {{&pyb_pin_type}, 3, FUNC_GPIO3, PERIPHS_IO_MUX_U0RXD_U},
68 {{&pyb_pin_type}, 4, FUNC_GPIO4, PERIPHS_IO_MUX_GPIO4_U},
69 {{&pyb_pin_type}, 5, FUNC_GPIO5, PERIPHS_IO_MUX_GPIO5_U},
Damien Georged9d40812016-04-13 22:45:51 +010070 {{NULL}, 0, 0, 0},
71 {{NULL}, 0, 0, 0},
72 {{NULL}, 0, 0, 0},
Damien Georgea9a732a2016-04-13 22:38:44 +010073 {{&pyb_pin_type}, 9, FUNC_GPIO9, PERIPHS_IO_MUX_SD_DATA2_U},
74 {{&pyb_pin_type}, 10, FUNC_GPIO10, PERIPHS_IO_MUX_SD_DATA3_U},
Damien Georged9d40812016-04-13 22:45:51 +010075 {{NULL}, 0, 0, 0},
Damien Georgea9a732a2016-04-13 22:38:44 +010076 {{&pyb_pin_type}, 12, FUNC_GPIO12, PERIPHS_IO_MUX_MTDI_U},
77 {{&pyb_pin_type}, 13, FUNC_GPIO13, PERIPHS_IO_MUX_MTCK_U},
78 {{&pyb_pin_type}, 14, FUNC_GPIO14, PERIPHS_IO_MUX_MTMS_U},
79 {{&pyb_pin_type}, 15, FUNC_GPIO15, PERIPHS_IO_MUX_MTDO_U},
Paul Sokolovskyeb247ea2016-01-08 22:04:00 +020080 // GPIO16 is special, belongs to different register set, and
81 // otherwise handled specially.
Damien Georgea9a732a2016-04-13 22:38:44 +010082 {{&pyb_pin_type}, 16, -1, -1},
Damien George87c62502015-02-13 22:21:44 +000083};
84
Paul Sokolovskyeb247ea2016-01-08 22:04:00 +020085STATIC uint8_t pin_mode[16 + 1];
Damien Georgecdad2b62015-12-28 17:42:20 +000086
Damien George674bf1b2016-04-14 11:15:43 +010087// forward declaration
88STATIC const pin_irq_obj_t pin_irq_obj[16];
89
90void pin_init0(void) {
91 ETS_GPIO_INTR_DISABLE();
92 ETS_GPIO_INTR_ATTACH(pin_intr_handler_iram, NULL);
93 // disable all interrupts
94 memset(&MP_STATE_PORT(pin_irq_handler)[0], 0, 16 * sizeof(mp_obj_t));
95 for (int p = 0; p < 16; ++p) {
96 GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << p);
97 SET_TRIGGER(p, 0);
98 }
99 ETS_GPIO_INTR_ENABLE();
100}
101
102void pin_intr_handler(uint32_t status) {
103 gc_lock();
104 status &= 0xffff;
105 for (int p = 0; status; ++p, status >>= 1) {
106 if (status & 1) {
107 mp_obj_t handler = MP_STATE_PORT(pin_irq_handler)[p];
108 if (handler != MP_OBJ_NULL) {
Paul Sokolovsky6d103b62016-04-25 19:28:12 +0300109 mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
Damien George674bf1b2016-04-14 11:15:43 +0100110 }
111 }
112 }
113 gc_unlock();
114}
115
Damien George7059c8c2016-02-11 11:41:58 +0000116pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) {
Damien George342d9032015-12-29 00:19:23 +0000117 if (mp_obj_get_type(pin_in) != &pyb_pin_type) {
118 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "expecting a pin"));
119 }
120 pyb_pin_obj_t *self = pin_in;
Damien George7059c8c2016-02-11 11:41:58 +0000121 return self;
122}
123
124uint mp_obj_get_pin(mp_obj_t pin_in) {
125 return mp_obj_get_pin_obj(pin_in)->phys_port;
Damien George342d9032015-12-29 00:19:23 +0000126}
127
Damien George68e222a2016-05-26 15:42:27 +0100128void mp_hal_pin_input(mp_hal_pin_obj_t pin_id) {
129 pin_mode[pin_id] = GPIO_MODE_INPUT;
130 if (pin_id == 16) {
131 WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1);
132 WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1);
133 WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input
134 } else {
135 const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id];
136 PIN_FUNC_SELECT(self->periph, self->func);
137 PIN_PULLUP_DIS(self->periph);
138 gpio_output_set(0, 0, 0, 1 << self->phys_port);
139 }
140}
141
142void mp_hal_pin_output(mp_hal_pin_obj_t pin_id) {
143 pin_mode[pin_id] = GPIO_MODE_OUTPUT;
144 if (pin_id == 16) {
145 WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1);
146 WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1);
147 WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); // output
148 } else {
149 const pyb_pin_obj_t *self = &pyb_pin_obj[pin_id];
150 PIN_FUNC_SELECT(self->periph, self->func);
151 PIN_PULLUP_DIS(self->periph);
152 gpio_output_set(0, 0, 1 << self->phys_port, 0);
153 }
154}
155
Damien George342d9032015-12-29 00:19:23 +0000156int pin_get(uint pin) {
Paul Sokolovskyeb247ea2016-01-08 22:04:00 +0200157 if (pin == 16) {
158 return READ_PERI_REG(RTC_GPIO_IN_DATA) & 1;
159 }
Damien George342d9032015-12-29 00:19:23 +0000160 return GPIO_INPUT_GET(pin);
161}
162
163void pin_set(uint pin, int value) {
Paul Sokolovskyeb247ea2016-01-08 22:04:00 +0200164 if (pin == 16) {
165 int out_en = (pin_mode[pin] == GPIO_MODE_OUTPUT);
166 WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1);
167 WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1);
168 WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | out_en);
169 WRITE_PERI_REG(RTC_GPIO_OUT, (READ_PERI_REG(RTC_GPIO_OUT) & ~1) | value);
170 return;
171 }
172
Damien Georgecdad2b62015-12-28 17:42:20 +0000173 uint32_t enable = 0;
174 uint32_t disable = 0;
Damien George342d9032015-12-29 00:19:23 +0000175 switch (pin_mode[pin]) {
Damien Georgecdad2b62015-12-28 17:42:20 +0000176 case GPIO_MODE_INPUT:
177 value = -1;
178 disable = 1;
179 break;
180
181 case GPIO_MODE_OUTPUT:
182 enable = 1;
183 break;
184
185 case GPIO_MODE_OPEN_DRAIN:
186 if (value == -1) {
187 return;
188 } else if (value == 0) {
189 enable = 1;
190 } else {
191 value = -1;
192 disable = 1;
193 }
194 break;
195 }
196
197 enable <<= pin;
198 disable <<= pin;
199 if (value == -1) {
200 gpio_output_set(0, 0, enable, disable);
201 } else {
202 gpio_output_set(value << pin, (1 - value) << pin, enable, disable);
203 }
204}
205
Damien George7f9d1d62015-04-09 23:56:15 +0100206STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
Damien George87c62502015-02-13 22:21:44 +0000207 pyb_pin_obj_t *self = self_in;
208
209 // pin name
Damien Georgea9a732a2016-04-13 22:38:44 +0100210 mp_printf(print, "Pin(%u)", self->phys_port);
Damien George87c62502015-02-13 22:21:44 +0000211}
212
Damien George8a3e9032016-05-03 13:13:56 +0100213// pin.init(mode, pull=None, *, value)
Damien George87c62502015-02-13 22:21:44 +0000214STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
Damien George9df6b3a2016-05-03 12:44:28 +0100215 enum { ARG_mode, ARG_pull, ARG_value };
Damien George87c62502015-02-13 22:21:44 +0000216 static const mp_arg_t allowed_args[] = {
217 { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
Damien George8a3e9032016-05-03 13:13:56 +0100218 { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
Damien Georgecdad2b62015-12-28 17:42:20 +0000219 { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
Damien George87c62502015-02-13 22:21:44 +0000220 };
221
222 // parse args
Damien George9df6b3a2016-05-03 12:44:28 +0100223 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
224 mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
Damien George87c62502015-02-13 22:21:44 +0000225
226 // get io mode
Damien George9df6b3a2016-05-03 12:44:28 +0100227 uint mode = args[ARG_mode].u_int;
Damien George87c62502015-02-13 22:21:44 +0000228
229 // get pull mode
Damien George8a3e9032016-05-03 13:13:56 +0100230 uint pull = GPIO_PULL_NONE;
231 if (args[ARG_pull].u_obj != mp_const_none) {
232 pull = mp_obj_get_int(args[ARG_pull].u_obj);
233 }
Damien Georgecdad2b62015-12-28 17:42:20 +0000234
235 // get initial value
236 int value;
Damien George9df6b3a2016-05-03 12:44:28 +0100237 if (args[ARG_value].u_obj == MP_OBJ_NULL) {
Damien Georgecdad2b62015-12-28 17:42:20 +0000238 value = -1;
239 } else {
Damien George9df6b3a2016-05-03 12:44:28 +0100240 value = mp_obj_is_true(args[ARG_value].u_obj);
Damien Georgecdad2b62015-12-28 17:42:20 +0000241 }
242
243 // save the mode
244 pin_mode[self->phys_port] = mode;
Damien George87c62502015-02-13 22:21:44 +0000245
246 // configure the GPIO as requested
Paul Sokolovskyeb247ea2016-01-08 22:04:00 +0200247 if (self->phys_port == 16) {
Damien George8a15e0b2016-08-10 12:45:40 +1000248 // only pull-down seems to be supported by the hardware, and
249 // we only expose pull-up behaviour in software
250 if (pull != GPIO_PULL_NONE) {
251 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin(16) doesn't support pull"));
252 }
Paul Sokolovskyeb247ea2016-01-08 22:04:00 +0200253 } else {
254 PIN_FUNC_SELECT(self->periph, self->func);
255 #if 0
256 // Removed in SDK 1.1.0
257 if ((pull & GPIO_PULL_DOWN) == 0) {
258 PIN_PULLDWN_DIS(self->periph);
259 }
260 #endif
261 if ((pull & GPIO_PULL_UP) == 0) {
262 PIN_PULLUP_DIS(self->periph);
263 }
264 #if 0
265 if ((pull & GPIO_PULL_DOWN) != 0) {
266 PIN_PULLDWN_EN(self->periph);
267 }
268 #endif
269 if ((pull & GPIO_PULL_UP) != 0) {
270 PIN_PULLUP_EN(self->periph);
271 }
Damien George87c62502015-02-13 22:21:44 +0000272 }
273
Damien George342d9032015-12-29 00:19:23 +0000274 pin_set(self->phys_port, value);
Damien George87c62502015-02-13 22:21:44 +0000275
276 return mp_const_none;
277}
278
279// constructor(id, ...)
Paul Sokolovskyeac22e22017-01-04 16:10:42 +0300280STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Damien George87c62502015-02-13 22:21:44 +0000281 mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
282
Damien Georged9d40812016-04-13 22:45:51 +0100283 // get the wanted pin object
Damien George87c62502015-02-13 22:21:44 +0000284 int wanted_pin = mp_obj_get_int(args[0]);
285 pyb_pin_obj_t *pin = NULL;
Damien Georged9d40812016-04-13 22:45:51 +0100286 if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(pyb_pin_obj)) {
287 pin = (pyb_pin_obj_t*)&pyb_pin_obj[wanted_pin];
Damien George87c62502015-02-13 22:21:44 +0000288 }
Damien Georged9d40812016-04-13 22:45:51 +0100289 if (pin == NULL || pin->base.type == NULL) {
Damien George87c62502015-02-13 22:21:44 +0000290 nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin"));
291 }
292
293 if (n_args > 1 || n_kw > 0) {
294 // pin mode given, so configure this GPIO
295 mp_map_t kw_args;
296 mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
297 pyb_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
298 }
299
300 return (mp_obj_t)pin;
301}
302
Damien Georgecdad2b62015-12-28 17:42:20 +0000303// fast method for getting/setting pin value
Paul Sokolovskyeac22e22017-01-04 16:10:42 +0300304STATIC mp_obj_t pyb_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
Damien Georgecdad2b62015-12-28 17:42:20 +0000305 mp_arg_check_num(n_args, n_kw, 0, 1, false);
306 pyb_pin_obj_t *self = self_in;
307 if (n_args == 0) {
308 // get pin
Damien Georgeb203c172016-08-10 12:44:47 +1000309 return MP_OBJ_NEW_SMALL_INT(pin_get(self->phys_port));
Damien Georgecdad2b62015-12-28 17:42:20 +0000310 } else {
311 // set pin
Damien George342d9032015-12-29 00:19:23 +0000312 pin_set(self->phys_port, mp_obj_is_true(args[0]));
Damien Georgecdad2b62015-12-28 17:42:20 +0000313 return mp_const_none;
314 }
315}
316
Damien George87c62502015-02-13 22:21:44 +0000317// pin.init(mode, pull)
318STATIC mp_obj_t pyb_pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
319 return pyb_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
320}
321MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_init_obj, 1, pyb_pin_obj_init);
322
323// pin.value([value])
324STATIC mp_obj_t pyb_pin_value(mp_uint_t n_args, const mp_obj_t *args) {
Damien Georgecdad2b62015-12-28 17:42:20 +0000325 return pyb_pin_call(args[0], n_args - 1, 0, args + 1);
Damien George87c62502015-02-13 22:21:44 +0000326}
327STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pin_value_obj, 1, 2, pyb_pin_value);
328
329// pin.low()
330STATIC mp_obj_t pyb_pin_low(mp_obj_t self_in) {
331 pyb_pin_obj_t *self = self_in;
Damien George342d9032015-12-29 00:19:23 +0000332 pin_set(self->phys_port, 0);
Damien George87c62502015-02-13 22:21:44 +0000333 return mp_const_none;
334}
335STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_low_obj, pyb_pin_low);
336
337// pin.high()
338STATIC mp_obj_t pyb_pin_high(mp_obj_t self_in) {
339 pyb_pin_obj_t *self = self_in;
Damien George342d9032015-12-29 00:19:23 +0000340 pin_set(self->phys_port, 1);
Damien George87c62502015-02-13 22:21:44 +0000341 return mp_const_none;
342}
343STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_high_obj, pyb_pin_high);
344
Damien George8e130fc2016-05-03 13:47:10 +0100345// pin.irq(*, trigger, handler=None)
346STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
347 enum { ARG_trigger, ARG_handler };
348 static const mp_arg_t allowed_args[] = {
349 { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
350 { MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
351 };
352 pyb_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
353 mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
354 mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
355
Damien George674bf1b2016-04-14 11:15:43 +0100356 if (self->phys_port >= 16) {
357 nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "pin does not have IRQ capabilities"));
358 }
359
Damien George8e130fc2016-05-03 13:47:10 +0100360 if (args[ARG_trigger].u_int != 0) {
Damien George674bf1b2016-04-14 11:15:43 +0100361 // configure irq
Damien George8e130fc2016-05-03 13:47:10 +0100362 mp_obj_t handler = args[ARG_handler].u_obj;
Damien George674bf1b2016-04-14 11:15:43 +0100363 if (handler == mp_const_none) {
364 handler = MP_OBJ_NULL;
365 }
366 ETS_GPIO_INTR_DISABLE();
367 MP_STATE_PORT(pin_irq_handler)[self->phys_port] = handler;
Damien George8e130fc2016-05-03 13:47:10 +0100368 SET_TRIGGER(self->phys_port, args[ARG_trigger].u_int);
Damien George674bf1b2016-04-14 11:15:43 +0100369 GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << self->phys_port);
370 ETS_GPIO_INTR_ENABLE();
371 }
372
373 // return the irq object
374 return MP_OBJ_FROM_PTR(&pin_irq_obj[self->phys_port]);
375}
Damien George8e130fc2016-05-03 13:47:10 +0100376STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_irq_obj, 1, pyb_pin_irq);
Damien George674bf1b2016-04-14 11:15:43 +0100377
Paul Sokolovsky18b68352017-01-01 19:02:28 +0300378STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode);
379STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
380 (void)errcode;
381 pyb_pin_obj_t *self = self_in;
382
383 switch (request) {
384 case MP_PIN_READ: {
385 return pin_get(self->phys_port);
386 }
387 case MP_PIN_WRITE: {
388 pin_set(self->phys_port, arg);
389 return 0;
390 }
391 }
392 return -1;
393}
394
Damien George87c62502015-02-13 22:21:44 +0000395STATIC const mp_map_elem_t pyb_pin_locals_dict_table[] = {
396 // instance methods
397 { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_pin_init_obj },
398 { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pyb_pin_value_obj },
399 { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pyb_pin_low_obj },
400 { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pyb_pin_high_obj },
Damien George674bf1b2016-04-14 11:15:43 +0100401 { MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_pin_irq_obj },
Damien George87c62502015-02-13 22:21:44 +0000402
403 // class constants
404 { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) },
Damien Georgecdad2b62015-12-28 17:42:20 +0000405 { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT) },
406 { MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OPEN_DRAIN) },
Damien George87c62502015-02-13 22:21:44 +0000407 { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_UP) },
Josef Gajdusek7d8edef2015-05-26 18:54:55 +0200408 //{ MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULL_DOWN) },
Damien George674bf1b2016-04-14 11:15:43 +0100409
410 // IRG triggers, can be or'd together
411 { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_PIN_INTR_POSEDGE) },
412 { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_PIN_INTR_NEGEDGE) },
Damien George87c62502015-02-13 22:21:44 +0000413};
414
415STATIC MP_DEFINE_CONST_DICT(pyb_pin_locals_dict, pyb_pin_locals_dict_table);
416
Paul Sokolovsky18b68352017-01-01 19:02:28 +0300417STATIC const mp_pin_p_t pin_pin_p = {
418 .ioctl = pin_ioctl,
419};
420
Damien George87c62502015-02-13 22:21:44 +0000421const mp_obj_type_t pyb_pin_type = {
422 { &mp_type_type },
423 .name = MP_QSTR_Pin,
424 .print = pyb_pin_print,
425 .make_new = pyb_pin_make_new,
Damien Georgecdad2b62015-12-28 17:42:20 +0000426 .call = pyb_pin_call,
Paul Sokolovsky18b68352017-01-01 19:02:28 +0300427 .protocol = &pin_pin_p,
Damien George87c62502015-02-13 22:21:44 +0000428 .locals_dict = (mp_obj_t)&pyb_pin_locals_dict,
429};
Damien George674bf1b2016-04-14 11:15:43 +0100430
431/******************************************************************************/
432// Pin IRQ object
433
434STATIC const mp_obj_type_t pin_irq_type;
435
436STATIC const pin_irq_obj_t pin_irq_obj[16] = {
437 {{&pin_irq_type}, 0},
438 {{&pin_irq_type}, 1},
439 {{&pin_irq_type}, 2},
440 {{&pin_irq_type}, 3},
441 {{&pin_irq_type}, 4},
442 {{&pin_irq_type}, 5},
443 {{&pin_irq_type}, 6},
444 {{&pin_irq_type}, 7},
445 {{&pin_irq_type}, 8},
446 {{&pin_irq_type}, 9},
447 {{&pin_irq_type}, 10},
448 {{&pin_irq_type}, 11},
449 {{&pin_irq_type}, 12},
450 {{&pin_irq_type}, 13},
451 {{&pin_irq_type}, 14},
452 {{&pin_irq_type}, 15},
453};
454
455STATIC mp_obj_t pin_irq_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
456 pin_irq_obj_t *self = self_in;
457 mp_arg_check_num(n_args, n_kw, 0, 0, false);
458 pin_intr_handler(1 << self->phys_port);
459 return mp_const_none;
460}
461
462STATIC mp_obj_t pin_irq_trigger(size_t n_args, const mp_obj_t *args) {
463 pin_irq_obj_t *self = args[0];
464 uint32_t orig_trig = GET_TRIGGER(self->phys_port);
465 if (n_args == 2) {
466 // set trigger
467 SET_TRIGGER(self->phys_port, mp_obj_get_int(args[1]));
468 }
469 // return original trigger value
470 return MP_OBJ_NEW_SMALL_INT(orig_trig);
471}
472STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_irq_trigger_obj, 1, 2, pin_irq_trigger);
473
474STATIC const mp_rom_map_elem_t pin_irq_locals_dict_table[] = {
475 { MP_ROM_QSTR(MP_QSTR_trigger), MP_ROM_PTR(&pin_irq_trigger_obj) },
476};
477
478STATIC MP_DEFINE_CONST_DICT(pin_irq_locals_dict, pin_irq_locals_dict_table);
479
480STATIC const mp_obj_type_t pin_irq_type = {
481 { &mp_type_type },
482 .name = MP_QSTR_IRQ,
483 .call = pin_irq_call,
484 .locals_dict = (mp_obj_dict_t*)&pin_irq_locals_dict,
485};