diff options
| author | Scott Shawcroft <scott@chickadee.tech> | 2016-08-24 17:38:08 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott@chickadee.tech> | 2016-08-24 17:38:08 -0700 |
| commit | 3cb4938c637290625d2fd71f7b4b94d385a4070b (patch) | |
| tree | 9cee8c43de12a32f541f25c876e4549bfb14a11d | |
| parent | dade18bddf2a700c372f64d0a859cd0d24ea98d0 (diff) | |
atmel-samd: Support Digital IO pins.
Also bumps up the heap size.
| -rw-r--r-- | atmel-samd/Makefile | 4 | ||||
| -rw-r--r-- | atmel-samd/boards/arduino_zero/pins.c | 75 | ||||
| -rw-r--r-- | atmel-samd/boards/arduino_zero/pins.h | 28 | ||||
| -rw-r--r-- | atmel-samd/boards/feather_m0_ble/pins.c | 78 | ||||
| -rw-r--r-- | atmel-samd/boards/feather_m0_ble/pins.h | 28 | ||||
| -rw-r--r-- | atmel-samd/main.c | 6 | ||||
| -rw-r--r-- | atmel-samd/modmachine.c | 51 | ||||
| -rw-r--r-- | atmel-samd/mpconfigport.h | 14 | ||||
| -rw-r--r-- | atmel-samd/pin.c | 438 | ||||
| -rw-r--r-- | atmel-samd/pin.h | 76 | ||||
| -rw-r--r-- | atmel-samd/pin_defs_samd.c | 57 | ||||
| -rw-r--r-- | atmel-samd/pin_named_pins.c | 60 |
12 files changed, 911 insertions, 4 deletions
diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index 015caece8..95d9b0691 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -109,8 +109,11 @@ SRC_ASF = $(addprefix asf/sam0/,\ SRC_C = \ main.c \ + modmachine.c \ modutime.c \ mphalport.c \ + pin.c \ + pin_named_pins.c \ uart.c \ asf/common/services/sleepmgr/samd/sleepmgr.c \ asf/common/services/usb/class/cdc/device/udi_cdc.c \ @@ -121,6 +124,7 @@ SRC_C = \ asf/sam0/utils/cmsis/samd21/source/gcc/startup_samd21.c \ asf/sam0/utils/cmsis/samd21/source/system_samd21.c \ asf/sam0/utils/syscalls/gcc/syscalls.c \ + boards/$(BOARD)/pins.c \ lib/utils/stdout_helpers.c \ lib/utils/printf.c \ lib/utils/pyexec.c \ diff --git a/atmel-samd/boards/arduino_zero/pins.c b/atmel-samd/boards/arduino_zero/pins.c new file mode 100644 index 000000000..fb255ef60 --- /dev/null +++ b/atmel-samd/boards/arduino_zero/pins.c @@ -0,0 +1,75 @@ +#include "pins.h" +#include "asf/sam0/drivers/system/system.h" + +#define PIN(p_name) \ +const pin_obj_t pin_## p_name = { \ + { &pin_type }, \ + .name = MP_QSTR_ ## p_name, \ + .pin = (PIN_## p_name), \ +} + +PIN(PA02); +PIN(PB08); +PIN(PB09); +PIN(PA04); +PIN(PA05); +PIN(PB02); +PIN(PA11); +PIN(PA10); +PIN(PA14); +PIN(PA09); +PIN(PA08); +PIN(PA15); +PIN(PA20); +PIN(PA06); +PIN(PA07); +PIN(PA18); +PIN(PA16); +PIN(PA19); +PIN(PA17); + +STATIC const mp_map_elem_t pin_cpu_pins_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_PA02), (mp_obj_t)&pin_PA02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PB08), (mp_obj_t)&pin_PB08 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PB09), (mp_obj_t)&pin_PB09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA04), (mp_obj_t)&pin_PA04 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA05), (mp_obj_t)&pin_PA05 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PB02), (mp_obj_t)&pin_PB02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA11), (mp_obj_t)&pin_PA11 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA10), (mp_obj_t)&pin_PA10 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA14), (mp_obj_t)&pin_PA14 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA09), (mp_obj_t)&pin_PA09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA08), (mp_obj_t)&pin_PA08 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA15), (mp_obj_t)&pin_PA15 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA20), (mp_obj_t)&pin_PA20 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA06), (mp_obj_t)&pin_PA06 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA07), (mp_obj_t)&pin_PA07 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA18), (mp_obj_t)&pin_PA18 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA16), (mp_obj_t)&pin_PA16 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA19), (mp_obj_t)&pin_PA19 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA17), (mp_obj_t)&pin_PA17 }, +}; +MP_DEFINE_CONST_DICT(pin_cpu_pins_locals_dict, pin_cpu_pins_locals_dict_table); + +STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), (mp_obj_t)&pin_PA02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), (mp_obj_t)&pin_PB08 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A2), (mp_obj_t)&pin_PB09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PA04 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PA05 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PB02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_0RX), (mp_obj_t)&pin_PA11 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_1TX), (mp_obj_t)&pin_PA10 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D2), (mp_obj_t)&pin_PA14 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D3), (mp_obj_t)&pin_PA09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D4), (mp_obj_t)&pin_PA08 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D5), (mp_obj_t)&pin_PA15 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D6), (mp_obj_t)&pin_PA20 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D8), (mp_obj_t)&pin_PA06 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA07 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D10), (mp_obj_t)&pin_PA18 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D11), (mp_obj_t)&pin_PA16 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA19 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA17 }, +}; +MP_DEFINE_CONST_DICT(pin_board_pins_locals_dict, pin_board_pins_locals_dict_table); diff --git a/atmel-samd/boards/arduino_zero/pins.h b/atmel-samd/boards/arduino_zero/pins.h new file mode 100644 index 000000000..2a1dbbf93 --- /dev/null +++ b/atmel-samd/boards/arduino_zero/pins.h @@ -0,0 +1,28 @@ + +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_FEATHER_M0_BLE_PINS_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_FEATHER_M0_BLE_PINS_H__ + +#include "pin.h" + +extern const pin_obj_t pin_PA02; +extern const pin_obj_t pin_PB08; +extern const pin_obj_t pin_PB09; +extern const pin_obj_t pin_PA04; +extern const pin_obj_t pin_PA05; +extern const pin_obj_t pin_PB02; +extern const pin_obj_t pin_PB11; +extern const pin_obj_t pin_PB10; +extern const pin_obj_t pin_PB21; +extern const pin_obj_t pin_PA11; +extern const pin_obj_t pin_PA10; +extern const pin_obj_t pin_PA22; +extern const pin_obj_t pin_PA23; +extern const pin_obj_t pin_PA15; +extern const pin_obj_t pin_PA20; +extern const pin_obj_t pin_PA07; +extern const pin_obj_t pin_PA18; +extern const pin_obj_t pin_PA16; +extern const pin_obj_t pin_PA19; +extern const pin_obj_t pin_PA17; + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_FEATHER_M0_BLE_PINS_H__ diff --git a/atmel-samd/boards/feather_m0_ble/pins.c b/atmel-samd/boards/feather_m0_ble/pins.c new file mode 100644 index 000000000..d487ac16f --- /dev/null +++ b/atmel-samd/boards/feather_m0_ble/pins.c @@ -0,0 +1,78 @@ +#include "pins.h" +#include "asf/sam0/drivers/system/system.h" + +#define PIN(p_name) \ +const pin_obj_t pin_## p_name = { \ + { &pin_type }, \ + .name = MP_QSTR_ ## p_name, \ + .pin = (PIN_## p_name), \ +} + +PIN(PA02); +PIN(PB08); +PIN(PB09); +PIN(PA04); +PIN(PA05); +PIN(PB02); +PIN(PB11); +PIN(PB10); +PIN(PA12); +PIN(PA11); +PIN(PA10); +PIN(PA22); +PIN(PA23); +PIN(PA15); +PIN(PA20); +PIN(PA07); +PIN(PA18); +PIN(PA16); +PIN(PA19); +PIN(PA17); + +STATIC const mp_map_elem_t pin_cpu_pins_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_PA02), (mp_obj_t)&pin_PA02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PB08), (mp_obj_t)&pin_PB08 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PB09), (mp_obj_t)&pin_PB09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA04), (mp_obj_t)&pin_PA04 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA05), (mp_obj_t)&pin_PA05 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PB02), (mp_obj_t)&pin_PB02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PB11), (mp_obj_t)&pin_PB11 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PB10), (mp_obj_t)&pin_PB10 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA12), (mp_obj_t)&pin_PA12 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA11), (mp_obj_t)&pin_PA11 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA10), (mp_obj_t)&pin_PA10 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA22), (mp_obj_t)&pin_PA22 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA23), (mp_obj_t)&pin_PA23 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA15), (mp_obj_t)&pin_PA15 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA20), (mp_obj_t)&pin_PA20 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA07), (mp_obj_t)&pin_PA07 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA18), (mp_obj_t)&pin_PA18 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA16), (mp_obj_t)&pin_PA16 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA19), (mp_obj_t)&pin_PA19 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA17), (mp_obj_t)&pin_PA17 }, +}; +MP_DEFINE_CONST_DICT(pin_cpu_pins_locals_dict, pin_cpu_pins_locals_dict_table); + +STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_A0), (mp_obj_t)&pin_PA02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A1), (mp_obj_t)&pin_PB08 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A2), (mp_obj_t)&pin_PB09 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A3), (mp_obj_t)&pin_PA04 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A4), (mp_obj_t)&pin_PA05 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_A5), (mp_obj_t)&pin_PB02 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_PB11 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_PB10 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_PA12 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_0RX), (mp_obj_t)&pin_PA11 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_1TX), (mp_obj_t)&pin_PA10 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_PA22 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PA23 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D5), (mp_obj_t)&pin_PA15 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D6), (mp_obj_t)&pin_PA20 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D9), (mp_obj_t)&pin_PA07 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D10), (mp_obj_t)&pin_PA18 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D11), (mp_obj_t)&pin_PA16 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA19 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA17 }, +}; +MP_DEFINE_CONST_DICT(pin_board_pins_locals_dict, pin_board_pins_locals_dict_table); diff --git a/atmel-samd/boards/feather_m0_ble/pins.h b/atmel-samd/boards/feather_m0_ble/pins.h new file mode 100644 index 000000000..2a1dbbf93 --- /dev/null +++ b/atmel-samd/boards/feather_m0_ble/pins.h @@ -0,0 +1,28 @@ + +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_FEATHER_M0_BLE_PINS_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_FEATHER_M0_BLE_PINS_H__ + +#include "pin.h" + +extern const pin_obj_t pin_PA02; +extern const pin_obj_t pin_PB08; +extern const pin_obj_t pin_PB09; +extern const pin_obj_t pin_PA04; +extern const pin_obj_t pin_PA05; +extern const pin_obj_t pin_PB02; +extern const pin_obj_t pin_PB11; +extern const pin_obj_t pin_PB10; +extern const pin_obj_t pin_PB21; +extern const pin_obj_t pin_PA11; +extern const pin_obj_t pin_PA10; +extern const pin_obj_t pin_PA22; +extern const pin_obj_t pin_PA23; +extern const pin_obj_t pin_PA15; +extern const pin_obj_t pin_PA20; +extern const pin_obj_t pin_PA07; +extern const pin_obj_t pin_PA18; +extern const pin_obj_t pin_PA16; +extern const pin_obj_t pin_PA19; +extern const pin_obj_t pin_PA17; + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_FEATHER_M0_BLE_PINS_H__ diff --git a/atmel-samd/main.c b/atmel-samd/main.c index cb722cc1a..2e7cc48a5 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -18,6 +18,7 @@ #include "asf/sam0/drivers/system/system.h" #include "mpconfigboard.h" +#include "pin.h" #include "uart.h" void do_str(const char *src, mp_parse_input_kind_t input_kind) { @@ -41,7 +42,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) { } static char *stack_top; -static char heap[2048]; +static char heap[8192]; int main(int argc, char **argv) { // initialise the cpu and peripherals @@ -57,6 +58,9 @@ int main(int argc, char **argv) { gc_init(heap, heap + sizeof(heap)); #endif mp_init(); + + pin_init0(); + #if MICROPY_REPL_EVENT_DRIVEN pyexec_event_repl_init(); for (;;) { diff --git a/atmel-samd/modmachine.c b/atmel-samd/modmachine.c new file mode 100644 index 000000000..f2e1b6de1 --- /dev/null +++ b/atmel-samd/modmachine.c @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2015 Damien P. George + * Copyright (c) 2016 Paul Sokolovsky + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdint.h> +#include <stdio.h> + +#include "py/obj.h" +#include "py/runtime.h" + +#include "pin.h" + +#if MICROPY_PY_MACHINE + +STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, + { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); + +const mp_obj_module_t machine_module = { + .base = { &mp_type_module }, + .name = MP_QSTR_umachine, + .globals = (mp_obj_dict_t*)&machine_module_globals, +}; + +#endif // MICROPY_PY_MACHINE diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h index 44bd57048..545b2c40d 100644 --- a/atmel-samd/mpconfigport.h +++ b/atmel-samd/mpconfigport.h @@ -53,7 +53,9 @@ #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) +#define MICROPY_PY_MACHINE (1) #define MICROPY_MODULE_WEAK_LINKS (1) +#define MICROPY_REPL_AUTO_INDENT (1) // type definitions for the specific machine @@ -78,17 +80,21 @@ typedef long mp_off_t; extern const struct _mp_obj_module_t machine_module; extern const struct _mp_obj_module_t utime_module; - //{ MP_OBJ_NEW_QSTR(MP_QSTR_umachine), (mp_obj_t)&machine_module }, #define MICROPY_PORT_BUILTIN_MODULES \ + { MP_OBJ_NEW_QSTR(MP_QSTR_umachine), (mp_obj_t)&machine_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module } \ #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ + { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module } \ - // board specific definitions #include "mpconfigboard.h" +#ifndef MICROPY_PIN_DEFS_PORT_H +#define MICROPY_PIN_DEFS_PORT_H "pins.h" +#endif + // We need to provide a declaration/definition of alloca() #include <alloca.h> @@ -105,6 +111,8 @@ extern const struct _mp_obj_module_t utime_module; #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ - vstr_t *repl_line; + vstr_t *repl_line; \ + mp_obj_t pin_class_mapper; \ + mp_obj_t pin_class_map_dict; \ #endif // __INCLUDED_MPCONFIGPORT_H diff --git a/atmel-samd/pin.c b/atmel-samd/pin.c new file mode 100644 index 000000000..5866c8bf0 --- /dev/null +++ b/atmel-samd/pin.c @@ -0,0 +1,438 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/mphal.h" +#include "pin.h" + +#include "asf/sam0/drivers/port/port.h" + +/// \moduleref machine +/// \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 = machine.Pin.board.X1 +/// +/// g = machine.Pin(machine.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: +/// +/// MyMapperDict = { 'LeftMotorDir' : pyb.Pin.cpu.C12 } +/// pyb.Pin.dict(MyMapperDict) +/// 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 bool pin_class_debug; + +void pin_init0(void) { + MP_STATE_PORT(pin_class_mapper) = mp_const_none; + MP_STATE_PORT(pin_class_map_dict) = mp_const_none; + pin_class_debug = false; +} + +// C API used to convert a user-supplied pin name into an ordinal pin number. +const pin_obj_t *pin_find(mp_obj_t user_obj) { + const pin_obj_t *pin_obj; + + // If a pin was provided, then use it + if (MP_OBJ_IS_TYPE(user_obj, &pin_type)) { + pin_obj = user_obj; + if (pin_class_debug) { + printf("Pin map passed pin "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + + if (MP_STATE_PORT(pin_class_mapper) != mp_const_none) { + pin_obj = mp_call_function_1(MP_STATE_PORT(pin_class_mapper), user_obj); + if (pin_obj != mp_const_none) { + if (!MP_OBJ_IS_TYPE(pin_obj, &pin_type)) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Pin.mapper didn't return a Pin object")); + } + if (pin_class_debug) { + printf("Pin.mapper maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + // The pin mapping function returned mp_const_none, fall through to + // other lookup methods. + } + + if (MP_STATE_PORT(pin_class_map_dict) != mp_const_none) { + mp_map_t *pin_map_map = mp_obj_dict_get_map(MP_STATE_PORT(pin_class_map_dict)); + mp_map_elem_t *elem = mp_map_lookup(pin_map_map, user_obj, MP_MAP_LOOKUP); + if (elem != NULL && elem->value != NULL) { + pin_obj = elem->value; + if (pin_class_debug) { + printf("Pin.map_dict maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + } + + // See if the pin name matches a board pin + pin_obj = pin_find_named_pin(&pin_board_pins_locals_dict, user_obj); + if (pin_obj) { + if (pin_class_debug) { + printf("Pin.board maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + + // See if the pin name matches a cpu pin + pin_obj = pin_find_named_pin(&pin_cpu_pins_locals_dict, user_obj); + if (pin_obj) { + if (pin_class_debug) { + printf("Pin.cpu maps "); + mp_obj_print(user_obj, PRINT_REPR); + printf(" to "); + mp_obj_print((mp_obj_t)pin_obj, PRINT_STR); + printf("\n"); + } + return pin_obj; + } + + 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))); +} + +/// \method __str__() +/// Return a string describing the pin object. +STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pin_obj_t *self = self_in; + + // pin name + mp_printf(print, "Pin(Pin.cpu.%q)", self->name); +} + +STATIC 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); + +/// \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(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + // Run an argument through the mapper and return the result. + const pin_obj_t *pin = pin_find(args[0]); + + if (n_args > 1 || n_kw > 0) { + // pin mode given, so configure this GPIO + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args); + } + + 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 + // TODO(tannewt): Do we need to switch read functions based on our direction? + return MP_OBJ_NEW_SMALL_INT(port_pin_get_input_level(self->pin)); + } else { + // set pin + port_pin_set_output_level(self->pin, mp_obj_is_true(args[0])); + 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) { + if (n_args > 1) { + MP_STATE_PORT(pin_class_mapper) = args[1]; + return mp_const_none; + } + return MP_STATE_PORT(pin_class_mapper); +} +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); + +/// \classmethod dict([dict]) +/// Get or set the pin mapper dictionary. +STATIC mp_obj_t pin_map_dict(mp_uint_t n_args, const mp_obj_t *args) { + if (n_args > 1) { + MP_STATE_PORT(pin_class_map_dict) = args[1]; + return mp_const_none; + } + return MP_STATE_PORT(pin_class_map_dict); +} +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); + +/// \classmethod debug([state]) +/// Get or set the debugging state (`True` or `False` for on or off). +STATIC mp_obj_t pin_debug(mp_uint_t n_args, const mp_obj_t *args) { + if (n_args > 1) { + pin_class_debug = mp_obj_is_true(args[1]); + return mp_const_none; + } + return mp_obj_new_bool(pin_class_debug); +} +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); + +// init(mode, pull=None, *, 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_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}}, + }; + + // parse args + 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 + enum port_pin_dir mode = args[0].u_int; + switch(mode) + { + case PORT_PIN_DIR_INPUT: + case PORT_PIN_DIR_OUTPUT: + case PORT_PIN_DIR_OUTPUT_WTH_READBACK: + //do the work + break; + + default: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin mode: %d", mode)); + } + + // get pull mode + enum port_pin_pull pull = PORT_PIN_PULL_NONE; + if (args[1].u_obj != mp_const_none) { + pull = mp_obj_get_int(args[1].u_obj); + } + switch(pull) + { + case PORT_PIN_PULL_NONE: + case PORT_PIN_PULL_UP: + case PORT_PIN_PULL_DOWN: + //do the work + break; + + default: + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid pin pull: %d", pull)); + } + + // if given, set the pin value before initialising to prevent glitches + if (args[2].u_obj != MP_OBJ_NULL) { + port_pin_set_output_level(self->pin, mp_obj_is_true(args[2].u_obj)); + } + + // configure the GPIO as requested + struct port_config pin_conf; + port_get_config_defaults(&pin_conf); + + pin_conf.direction = mode; + pin_conf.input_pull = pull; + port_pin_set_config(self->pin, &pin_conf); + + return mp_const_none; +} + +STATIC mp_obj_t pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + return pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); +} +MP_DEFINE_CONST_FUN_OBJ_KW(pin_init_obj, 1, 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(mp_uint_t n_args, const mp_obj_t *args) { + 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); + +/// \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; + port_pin_set_output_level(self->pin, false); + return mp_const_none; +} +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; + port_pin_set_output_level(self->pin, true); + return mp_const_none; +} +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(self->name); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_name_obj, pin_name); + +/// \method names() +/// Returns the cpu and board names for this pin. +STATIC mp_obj_t pin_names(mp_obj_t self_in) { + pin_obj_t *self = self_in; + mp_obj_t result = mp_obj_new_list(0, NULL); + mp_obj_list_append(result, MP_OBJ_NEW_QSTR(self->name)); + + mp_map_t *map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict); + mp_map_elem_t *elem = map->table; + + for (mp_uint_t i = 0; i < map->used; i++, elem++) { + if (elem->value == self) { + mp_obj_list_append(result, elem->key); + } + } + return result; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_names_obj, pin_names); + +/// \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(self->pin); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_pin_obj, pin_pin); + +/// \method gpio() +/// Returns the base address of the GPIO block associated with this pin. +STATIC mp_obj_t pin_gpio(mp_obj_t self_in) { + pin_obj_t *self = self_in; + return MP_OBJ_NEW_SMALL_INT((mp_int_t)port_get_group_from_gpio_pin(self->pin)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_gpio_obj, pin_gpio); + +STATIC const mp_map_elem_t pin_locals_dict_table[] = { + // instance methods + { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pin_init_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pin_value_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pin_low_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pin_high_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_name_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_names), (mp_obj_t)&pin_names_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&pin_pin_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_gpio), (mp_obj_t)&pin_gpio_obj }, + + // class methods + { MP_OBJ_NEW_QSTR(MP_QSTR_mapper), (mp_obj_t)&pin_mapper_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&pin_map_dict_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_debug), (mp_obj_t)&pin_debug_obj }, + + // class attributes + { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&pin_board_pins_obj_type }, + { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type }, + + // class constants + { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(PORT_PIN_DIR_INPUT) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(PORT_PIN_DIR_OUTPUT) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(PORT_PIN_PULL_NONE) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(PORT_PIN_PULL_UP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(PORT_PIN_PULL_DOWN) }, +}; + +STATIC MP_DEFINE_CONST_DICT(pin_locals_dict, pin_locals_dict_table); + +const mp_obj_type_t pin_type = { + { &mp_type_type }, + .name = MP_QSTR_Pin, + .print = pin_print, + .make_new = pin_make_new, + .call = pin_call, + .locals_dict = (mp_obj_t)&pin_locals_dict, +}; diff --git a/atmel-samd/pin.h b/atmel-samd/pin.h new file mode 100644 index 000000000..0c071c099 --- /dev/null +++ b/atmel-samd/pin.h @@ -0,0 +1,76 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_PIN_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_PIN_H__ + +// This file requires pin_defs_xxx.h (which has port specific enums and +// defines, so we include it here. It should never be included directly + +#include "mpconfigport.h" + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + qstr name; + uint32_t pin; +} pin_obj_t; + +extern const mp_obj_type_t pin_type; + +typedef struct { + const char *name; + const pin_obj_t *pin; +} pin_named_pin_t; + +extern const pin_named_pin_t pin_board_pins[]; +extern const pin_named_pin_t pin_cpu_pins[]; + +//extern pin_map_obj_t pin_map_obj; + +typedef struct { + mp_obj_base_t base; + qstr name; + const pin_named_pin_t *named_pins; +} pin_named_pins_obj_t; + +extern const mp_obj_type_t pin_board_pins_obj_type; +extern const mp_obj_type_t pin_cpu_pins_obj_type; + +extern const mp_obj_dict_t pin_cpu_pins_locals_dict; +extern const mp_obj_dict_t pin_board_pins_locals_dict; + +MP_DECLARE_CONST_FUN_OBJ(pin_init_obj); + +void pin_init0(void); +uint32_t pin_get_mode(const pin_obj_t *pin); +uint32_t pin_get_pull(const pin_obj_t *pin); +uint32_t pin_get_af(const pin_obj_t *pin); +const pin_obj_t *pin_find(mp_obj_t user_obj); +const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name); + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_PIN_H__ diff --git a/atmel-samd/pin_defs_samd.c b/atmel-samd/pin_defs_samd.c new file mode 100644 index 000000000..2ffce5234 --- /dev/null +++ b/atmel-samd/pin_defs_samd.c @@ -0,0 +1,57 @@ +#include <stdint.h> +#include "pin.h" + +// Returns the pin mode. This value returned by this macro should be one of: +// GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD, +// GPIO_MODE_AF_PP, GPIO_MODE_AF_OD, or GPIO_MODE_ANALOG. + +uint32_t pin_get_mode(const pin_obj_t *pin) { + if (pin->gpio == NULL) { + // Analog only pin + return GPIO_MODE_ANALOG; + } + volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin); + uint32_t pcr = *port_pcr; + uint32_t af = (pcr & PORT_PCR_MUX_MASK) >> 8; + if (af == 0) { + return GPIO_MODE_ANALOG; + } + if (af == 1) { + if (pin->gpio->PDDR & (1 << pin->pin)) { + if (pcr & PORT_PCR_ODE) { + return GPIO_MODE_OUTPUT_OD; + } + return GPIO_MODE_OUTPUT_PP; + } + return GPIO_MODE_INPUT; + } + + if (pcr & PORT_PCR_ODE) { + return GPIO_MODE_AF_OD; + } + return GPIO_MODE_AF_PP; +} + +// Returns the pin pullup/pulldown. The value returned by this macro should +// be one of GPIO_NOPULL, GPIO_PULLUP, or GPIO_PULLDOWN. + +uint32_t pin_get_pull(const pin_obj_t *pin) { + if (pin->gpio == NULL) { + // Analog only pin + return GPIO_NOPULL; + } + volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin); + + uint32_t pcr = *port_pcr; + uint32_t af = (pcr & PORT_PCR_MUX_MASK) >> 8; + + // pull is only valid for digital modes (hence the af > 0 test) + + if (af > 0 && (pcr & PORT_PCR_PE) != 0) { + if (pcr & PORT_PCR_PS) { + return GPIO_PULLUP; + } + return GPIO_PULLDOWN; + } + return GPIO_NOPULL; +} diff --git a/atmel-samd/pin_named_pins.c b/atmel-samd/pin_named_pins.c new file mode 100644 index 000000000..c05f59903 --- /dev/null +++ b/atmel-samd/pin_named_pins.c @@ -0,0 +1,60 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> +#include <string.h> + +#include "py/runtime.h" +#include "py/mphal.h" +#include "pin.h" + +STATIC void pin_named_pins_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + pin_named_pins_obj_t *self = self_in; + mp_printf(print, "<Pin.%q>", self->name); +} + +const mp_obj_type_t pin_cpu_pins_obj_type = { + { &mp_type_type }, + .name = MP_QSTR_cpu, + .print = pin_named_pins_obj_print, + .locals_dict = (mp_obj_t)&pin_cpu_pins_locals_dict, +}; + +const mp_obj_type_t pin_board_pins_obj_type = { + { &mp_type_type }, + .name = MP_QSTR_board, + .print = pin_named_pins_obj_print, + .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict, +}; + +const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { + mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins); + mp_map_elem_t *named_elem = mp_map_lookup(named_map, name, MP_MAP_LOOKUP); + if (named_elem != NULL && named_elem->value != NULL) { + return named_elem->value; + } + return NULL; +} |
