diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index 8f89d83dd1..90bde67a5b 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -31,7 +31,6 @@ INC += -I. INC += -I.. INC += -I../lib/mp-readline INC += -I../lib/timeutils -INC += -Icommon-hal/modules/ INC += -Iasf_conf/ INC += -Iasf/common/boards/ INC += -Iasf/common/services/sleepmgr/ @@ -79,7 +78,23 @@ CFLAGS_CORTEX_M0 = \ -msoft-float \ -mfloat-abi=soft \ -fsingle-precision-constant \ + -fno-strict-aliasing \ -Wdouble-promotion \ + -Wno-endif-labels \ + -Wstrict-prototypes \ + -Werror-implicit-function-declaration \ + -Wpointer-arith \ + -Wfloat-equal \ + -Wundef \ + -Wshadow \ + -Wwrite-strings \ + -Wsign-compare \ + -Wmissing-format-attribute \ + -Wno-deprecated-declarations \ + -Wpacked \ + -Wnested-externs \ + -Wunreachable-code \ + -Wcast-align \ -D__SAMD21G18A__ \ -DUSB_DEVICE_PRODUCT_ID=$(USB_PID) \ -DUSB_DEVICE_VENDOR_ID=$(USB_VID) \ @@ -92,9 +107,15 @@ CFLAGS_CORTEX_M0 = \ -DEXTINT_CALLBACK_MODE=true \ -DUDD_ENABLE \ -DUSART_CALLBACK_MODE=true \ + -DSPI_CALLBACK_MODE=false \ + -DI2C_MASTER_CALLBACK_MODE=false \ + -DDAC_CALLBACK_MODE=false \ + -DTCC_ASYNC=false \ + -DADC_CALLBACK_MODE=false \ -DTC_ASYNC=true \ - -DUSB_DEVICE_LPM_SUPPORT -CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M0) $(COPT) + -DUSB_DEVICE_LPM_SUPPORT \ + --param max-inline-insns-single=500 +CFLAGS = $(INC) -Wall -Werror -std=gnu11 -nostdlib $(CFLAGS_CORTEX_M0) $(COPT) #Debugging/Optimization # TODO(tannewt): Figure out what NDEBUG does. Adding it to the debug build @@ -154,17 +175,10 @@ SRC_C = \ builtin_open.c \ fatfs_port.c \ main.c \ - modmachine.c \ - modmachine_adc.c \ - modmachine_dac.c \ - modmachine_pin.c \ - modmachine_pwm.c \ - modneopixel_write.c \ moduos.c \ - modutime.c \ mphalport.c \ - pin_named_pins.c \ - samdneopixel.c \ + samd21_pins.c \ + neopixel_status.c \ tick.c \ $(FLASH_IMPL) \ asf/common/services/sleepmgr/samd/sleepmgr.c \ @@ -178,7 +192,6 @@ 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/samd21_pins.c \ boards/$(BOARD)/init.c \ boards/$(BOARD)/pins.c \ lib/fatfs/ff.c \ @@ -194,12 +207,19 @@ STM_SRC_C = $(addprefix stmhal/,\ input.c \ ) -# TODO(tannewt): Use this sed line to extract the RST docs from these sources: -# sed': sed -n 's+^//|++p' ../api/machine.c -# -# RST lines are prefixed with //| SRC_BINDINGS = \ - modules/machine.c + board/__init__.c \ + microcontroller/__init__.c \ + microcontroller/Pin.c \ + nativeio/__init__.c \ + nativeio/AnalogIn.c \ + nativeio/AnalogOut.c \ + nativeio/DigitalInOut.c \ + nativeio/I2C.c \ + nativeio/PWMOut.c \ + nativeio/SPI.c \ + neopixel_write/__init__.c \ + time/__init__.c SRC_BINDINGS_EXPANDED = $(addprefix shared-bindings/, $(SRC_BINDINGS)) \ $(addprefix common-hal/, $(SRC_BINDINGS)) diff --git a/atmel-samd/autoreset.h b/atmel-samd/autoreset.h index 51b8285e70..5719aaa2f1 100644 --- a/atmel-samd/autoreset.h +++ b/atmel-samd/autoreset.h @@ -31,11 +31,11 @@ extern volatile bool reset_next_character; -void autoreset_tick(); +void autoreset_tick(void); -void autoreset_start(); -void autoreset_stop(); -void autoreset_enable(); -void autoreset_disable(); +void autoreset_start(void); +void autoreset_stop(void); +void autoreset_enable(void); +void autoreset_disable(void); #endif // __MICROPY_INCLUDED_ATMEL_SAMD_AUTORESET_H__ diff --git a/atmel-samd/boards/arduino_zero/conf_usb.h b/atmel-samd/boards/arduino_zero/conf_usb.h index 4702fe93b1..bdd5f9b5ea 100644 --- a/atmel-samd/boards/arduino_zero/conf_usb.h +++ b/atmel-samd/boards/arduino_zero/conf_usb.h @@ -87,9 +87,9 @@ void usb_rts_notify(uint8_t port, bool set); //! Interface callback definition #define UDI_MSC_ENABLE_EXT() mp_msc_enable() -extern bool mp_msc_enable(); +extern bool mp_msc_enable(void); #define UDI_MSC_DISABLE_EXT() mp_msc_disable() -extern void mp_msc_disable(); +extern void mp_msc_disable(void); //! Enable id string of interface to add an extra USB string #define UDI_MSC_STRING_ID 5 diff --git a/atmel-samd/boards/arduino_zero/mpconfigboard.h b/atmel-samd/boards/arduino_zero/mpconfigboard.h index fc778a7827..d055b0d0da 100644 --- a/atmel-samd/boards/arduino_zero/mpconfigboard.h +++ b/atmel-samd/boards/arduino_zero/mpconfigboard.h @@ -7,6 +7,8 @@ #define MICROPY_HW_LED_TX PIN_PA27 #define MICROPY_HW_LED_RX PIN_PB03 -#define MICROPY_HW_NEOPIXEL PIN_PB22 +#define MICROPY_HW_NEOPIXEL &pin_PB22 #define AUTORESET_DELAY_MS 500 + +#define FLASH_INCLUDE "internal_flash.h" diff --git a/atmel-samd/boards/arduino_zero/pins.c b/atmel-samd/boards/arduino_zero/pins.c index bb4836af19..b6c2336f74 100644 --- a/atmel-samd/boards/arduino_zero/pins.c +++ b/atmel-samd/boards/arduino_zero/pins.c @@ -1,6 +1,8 @@ -#include "boards/samd21_pins.h" +#include "shared-bindings/board/__init__.h" -STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { +#include "samd21_pins.h" + +STATIC const mp_map_elem_t board_global_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 }, @@ -27,4 +29,4 @@ STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { { 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_DEFINE_CONST_DICT(pin_board_pins_locals_dict, pin_board_pins_locals_dict_table); +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/atmel-samd/boards/feather_m0_adalogger/conf_usb.h b/atmel-samd/boards/feather_m0_adalogger/conf_usb.h index d4367f90f8..0834403c65 100644 --- a/atmel-samd/boards/feather_m0_adalogger/conf_usb.h +++ b/atmel-samd/boards/feather_m0_adalogger/conf_usb.h @@ -87,9 +87,9 @@ void usb_rts_notify(uint8_t port, bool set); //! Interface callback definition #define UDI_MSC_ENABLE_EXT() mp_msc_enable() -extern bool mp_msc_enable(); +extern bool mp_msc_enable(void); #define UDI_MSC_DISABLE_EXT() mp_msc_disable() -extern void mp_msc_disable(); +extern void mp_msc_disable(void); //! Enable id string of interface to add an extra USB string #define UDI_MSC_STRING_ID 5 diff --git a/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h b/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h index 9c656863b6..a3a4fef769 100644 --- a/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h +++ b/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h @@ -7,3 +7,5 @@ #define MICROPY_HW_MCU_NAME "samd21g18" #define AUTORESET_DELAY_MS 500 + +#define FLASH_INCLUDE "internal_flash.h" diff --git a/atmel-samd/boards/feather_m0_adalogger/pins.c b/atmel-samd/boards/feather_m0_adalogger/pins.c index dd57b57101..d109d6987f 100644 --- a/atmel-samd/boards/feather_m0_adalogger/pins.c +++ b/atmel-samd/boards/feather_m0_adalogger/pins.c @@ -1,6 +1,6 @@ -#include "boards/samd21_pins.h" +#include "samd21_pins.h" -STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { +STATIC const mp_map_elem_t board_global_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 }, @@ -23,4 +23,4 @@ STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { { 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); +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/atmel-samd/boards/feather_m0_basic/conf_usb.h b/atmel-samd/boards/feather_m0_basic/conf_usb.h index 89fa1620a1..5919bb7864 100644 --- a/atmel-samd/boards/feather_m0_basic/conf_usb.h +++ b/atmel-samd/boards/feather_m0_basic/conf_usb.h @@ -87,9 +87,9 @@ void usb_rts_notify(uint8_t port, bool set); //! Interface callback definition #define UDI_MSC_ENABLE_EXT() mp_msc_enable() -extern bool mp_msc_enable(); +extern bool mp_msc_enable(void); #define UDI_MSC_DISABLE_EXT() mp_msc_disable() -extern void mp_msc_disable(); +extern void mp_msc_disable(void); //! Enable id string of interface to add an extra USB string #define UDI_MSC_STRING_ID 5 diff --git a/atmel-samd/boards/feather_m0_basic/mpconfigboard.h b/atmel-samd/boards/feather_m0_basic/mpconfigboard.h index fa3ffc01a3..51ac9da85d 100644 --- a/atmel-samd/boards/feather_m0_basic/mpconfigboard.h +++ b/atmel-samd/boards/feather_m0_basic/mpconfigboard.h @@ -7,3 +7,5 @@ #define MICROPY_HW_MCU_NAME "samd21g18" #define AUTORESET_DELAY_MS 500 + +#define FLASH_INCLUDE "internal_flash.h" diff --git a/atmel-samd/boards/feather_m0_basic/pins.c b/atmel-samd/boards/feather_m0_basic/pins.c index b482e53f29..8eac1713fb 100644 --- a/atmel-samd/boards/feather_m0_basic/pins.c +++ b/atmel-samd/boards/feather_m0_basic/pins.c @@ -1,6 +1,6 @@ -#include "boards/samd21_pins.h" +#include "samd21_pins.h" -STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { +STATIC const mp_map_elem_t board_global_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 }, @@ -22,4 +22,4 @@ STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { { 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); +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/atmel-samd/boards/feather_m0_flash/conf_usb.h b/atmel-samd/boards/feather_m0_flash/conf_usb.h index 89fa1620a1..5919bb7864 100644 --- a/atmel-samd/boards/feather_m0_flash/conf_usb.h +++ b/atmel-samd/boards/feather_m0_flash/conf_usb.h @@ -87,9 +87,9 @@ void usb_rts_notify(uint8_t port, bool set); //! Interface callback definition #define UDI_MSC_ENABLE_EXT() mp_msc_enable() -extern bool mp_msc_enable(); +extern bool mp_msc_enable(void); #define UDI_MSC_DISABLE_EXT() mp_msc_disable() -extern void mp_msc_disable(); +extern void mp_msc_disable(void); //! Enable id string of interface to add an extra USB string #define UDI_MSC_STRING_ID 5 diff --git a/atmel-samd/boards/feather_m0_flash/mpconfigboard.h b/atmel-samd/boards/feather_m0_flash/mpconfigboard.h index b7fc593bd7..067f954a8b 100644 --- a/atmel-samd/boards/feather_m0_flash/mpconfigboard.h +++ b/atmel-samd/boards/feather_m0_flash/mpconfigboard.h @@ -19,3 +19,5 @@ #define SPI_FLASH_SERCOM SERCOM4 #define AUTORESET_DELAY_MS 500 + +#define FLASH_INCLUDE "spi_flash.h" diff --git a/atmel-samd/boards/metro_m0_flash/conf_usb.h b/atmel-samd/boards/metro_m0_flash/conf_usb.h index c54359562c..d6af74997b 100644 --- a/atmel-samd/boards/metro_m0_flash/conf_usb.h +++ b/atmel-samd/boards/metro_m0_flash/conf_usb.h @@ -87,9 +87,9 @@ void usb_rts_notify(uint8_t port, bool set); //! Interface callback definition #define UDI_MSC_ENABLE_EXT() mp_msc_enable() -extern bool mp_msc_enable(); +extern bool mp_msc_enable(void); #define UDI_MSC_DISABLE_EXT() mp_msc_disable() -extern void mp_msc_disable(); +extern void mp_msc_disable(void); //! Enable id string of interface to add an extra USB string #define UDI_MSC_STRING_ID 5 diff --git a/atmel-samd/boards/metro_m0_flash/mpconfigboard.h b/atmel-samd/boards/metro_m0_flash/mpconfigboard.h index 4b2f31b50b..a2f59b361a 100644 --- a/atmel-samd/boards/metro_m0_flash/mpconfigboard.h +++ b/atmel-samd/boards/metro_m0_flash/mpconfigboard.h @@ -8,7 +8,7 @@ #define MICROPY_HW_LED_TX PIN_PA27 #define MICROPY_HW_LED_RX PIN_PB03 -#define MICROPY_HW_NEOPIXEL PIN_PA30 +#define MICROPY_HW_NEOPIXEL &pin_PA30 #define SPI_FLASH_BAUDRATE (1000000) @@ -33,3 +33,5 @@ #define SPI_FLASH_SERCOM SERCOM4 #define AUTORESET_DELAY_MS 500 + +#define FLASH_INCLUDE "spi_flash.h" diff --git a/atmel-samd/boards/metro_m0_flash/pins.c b/atmel-samd/boards/metro_m0_flash/pins.c index 0fb0815d2a..baef1f8536 100644 --- a/atmel-samd/boards/metro_m0_flash/pins.c +++ b/atmel-samd/boards/metro_m0_flash/pins.c @@ -1,6 +1,6 @@ -#include "boards/samd21_pins.h" +#include "samd21_pins.h" -STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { +STATIC const mp_map_elem_t board_global_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 }, @@ -30,4 +30,4 @@ STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_FLASH_MISO), (mp_obj_t)&pin_PA12 }, { MP_OBJ_NEW_QSTR(MP_QSTR_FLASH_CS), (mp_obj_t)&pin_PA13 }, }; -MP_DEFINE_CONST_DICT(pin_board_pins_locals_dict, pin_board_pins_locals_dict_table); +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/atmel-samd/boards/samd21_pins.h b/atmel-samd/boards/samd21_pins.h deleted file mode 100644 index 7c65ec30d7..0000000000 --- a/atmel-samd/boards/samd21_pins.h +++ /dev/null @@ -1,166 +0,0 @@ -#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H__ -#define __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H__ - -#include "modmachine_pin.h" - -// Pins in datasheet order. -#ifdef PIN_PA00 -extern const pin_obj_t pin_PA00; -#endif -#ifdef PIN_PA01 -extern const pin_obj_t pin_PA01; -#endif -#ifdef PIN_PA02 -extern const pin_obj_t pin_PA02; -#endif -#ifdef PIN_PA03 -extern const pin_obj_t pin_PA03; -#endif -#ifdef PIN_PB04 -extern const pin_obj_t pin_PB04; -#endif -#ifdef PIN_PB05 -extern const pin_obj_t pin_PB05; -#endif -#ifdef PIN_PB06 -extern const pin_obj_t pin_PB06; -#endif -#ifdef PIN_PB07 -extern const pin_obj_t pin_PB07; -#endif -#ifdef PIN_PB08 -extern const pin_obj_t pin_PB08; -#endif -#ifdef PIN_PB09 -extern const pin_obj_t pin_PB09; -#endif -#ifdef PIN_PA04 -extern const pin_obj_t pin_PA04; -#endif -#ifdef PIN_PA05 -extern const pin_obj_t pin_PA05; -#endif -#ifdef PIN_PA06 -extern const pin_obj_t pin_PA06; -#endif -#ifdef PIN_PA07 -extern const pin_obj_t pin_PA07; -#endif -#ifdef PIN_PA08 -extern const pin_obj_t pin_PA08; -#endif -#ifdef PIN_PA09 -extern const pin_obj_t pin_PA09; -#endif -#ifdef PIN_PA10 -extern const pin_obj_t pin_PA10; -#endif -#ifdef PIN_PA11 -extern const pin_obj_t pin_PA11; -#endif -#ifdef PIN_PB10 -extern const pin_obj_t pin_PB10; -#endif -#ifdef PIN_PB11 -extern const pin_obj_t pin_PB11; -#endif -#ifdef PIN_PB12 -extern const pin_obj_t pin_PB12; -#endif -#ifdef PIN_PB13 -extern const pin_obj_t pin_PB13; -#endif -#ifdef PIN_PB14 -extern const pin_obj_t pin_PB14; -#endif - -// Second page. -#ifdef PIN_PB15 -extern const pin_obj_t pin_PB15; -#endif -#ifdef PIN_PA12 -extern const pin_obj_t pin_PA12; -#endif -#ifdef PIN_PA13 -extern const pin_obj_t pin_PA13; -#endif -#ifdef PIN_PA14 -extern const pin_obj_t pin_PA14; -#endif -#ifdef PIN_PA15 -extern const pin_obj_t pin_PA15; -#endif -#ifdef PIN_PA16 -extern const pin_obj_t pin_PA16; -#endif -#ifdef PIN_PA17 -extern const pin_obj_t pin_PA17; -#endif -#ifdef PIN_PA18 -extern const pin_obj_t pin_PA18; -#endif -#ifdef PIN_PA19 -extern const pin_obj_t pin_PA19; -#endif -#ifdef PIN_PB16 -extern const pin_obj_t pin_PB16; -#endif -#ifdef PIN_PB17 -extern const pin_obj_t pin_PB17; -#endif -#ifdef PIN_PA20 -extern const pin_obj_t pin_PA20; -#endif -#ifdef PIN_PA21 -extern const pin_obj_t pin_PA21; -#endif -#ifdef PIN_PA22 -extern const pin_obj_t pin_PA22; -#endif -#ifdef PIN_PA23 -extern const pin_obj_t pin_PA23; -#endif -#ifdef PIN_PA24 -extern const pin_obj_t pin_PA24; -#endif -#ifdef PIN_PA25 -extern const pin_obj_t pin_PA25; -#endif -#ifdef PIN_PB22 -extern const pin_obj_t pin_PB22; -#endif -#ifdef PIN_PB23 -extern const pin_obj_t pin_PB23; -#endif -#ifdef PIN_PA27 -extern const pin_obj_t pin_PA27; -#endif -#ifdef PIN_PA28 -extern const pin_obj_t pin_PA28; -#endif -#ifdef PIN_PA30 -extern const pin_obj_t pin_PA30; -#endif -#ifdef PIN_PA31 -extern const pin_obj_t pin_PA31; -#endif -#ifdef PIN_PB30 -extern const pin_obj_t pin_PB30; -#endif -#ifdef PIN_PB31 -extern const pin_obj_t pin_PB31; -#endif -#ifdef PIN_PB00 -extern const pin_obj_t pin_PB00; -#endif -#ifdef PIN_PB01 -extern const pin_obj_t pin_PB01; -#endif -#ifdef PIN_PB02 -extern const pin_obj_t pin_PB02; -#endif -#ifdef PIN_PB03 -extern const pin_obj_t pin_PB03; -#endif - -#endif // __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H__ diff --git a/atmel-samd/modmachine_dac.h b/atmel-samd/common-hal/board/__init__.c similarity index 84% rename from atmel-samd/modmachine_dac.h rename to atmel-samd/common-hal/board/__init__.c index 931987cd95..acab1ac078 100644 --- a/atmel-samd/modmachine_dac.h +++ b/atmel-samd/common-hal/board/__init__.c @@ -24,4 +24,11 @@ * THE SOFTWARE. */ -extern const mp_obj_type_t dac_type; +#include + +#include "py/runtime.h" +#include "py/mphal.h" +#include "common-hal/microcontroller/types.h" + +// Pins aren't actually defined here. They are in the board specific directory +// such as boards/arduino_zero/pins.c. diff --git a/atmel-samd/common-hal/microcontroller/Pin.c b/atmel-samd/common-hal/microcontroller/Pin.c new file mode 100644 index 0000000000..2e8b72a2c0 --- /dev/null +++ b/atmel-samd/common-hal/microcontroller/Pin.c @@ -0,0 +1 @@ +// Pins have no behavior. diff --git a/atmel-samd/common-hal/microcontroller/__init__.c b/atmel-samd/common-hal/microcontroller/__init__.c new file mode 100644 index 0000000000..260e2c1b54 --- /dev/null +++ b/atmel-samd/common-hal/microcontroller/__init__.c @@ -0,0 +1,197 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 "py/mphal.h" + +#include "samd21_pins.h" + +void common_hal_mcu_delay_us(uint32_t delay) { + mp_hal_delay_us(delay); +} + +// This maps MCU pin names to pin objects. +STATIC const mp_map_elem_t mcu_pin_global_dict_table[] = { +// Pins in datasheet order. +#ifdef PIN_PA00 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA00), (mp_obj_t)&pin_PA00 }, +#endif +#ifdef PIN_PA01 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA01), (mp_obj_t)&pin_PA01 }, +#endif +#ifdef PIN_PA02 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA02), (mp_obj_t)&pin_PA02 }, +#endif +#ifdef PIN_PA03 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA03), (mp_obj_t)&pin_PA03 }, +#endif +#ifdef PIN_PB04 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB04), (mp_obj_t)&pin_PB04 }, +#endif +#ifdef PIN_PB05 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB05), (mp_obj_t)&pin_PB05 }, +#endif +#ifdef PIN_PB06 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB06), (mp_obj_t)&pin_PB06 }, +#endif +#ifdef PIN_PB07 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB07), (mp_obj_t)&pin_PB07 }, +#endif +#ifdef PIN_PB08 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB08), (mp_obj_t)&pin_PB08 }, +#endif +#ifdef PIN_PB09 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB09), (mp_obj_t)&pin_PB09 }, +#endif +#ifdef PIN_PA04 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA04), (mp_obj_t)&pin_PA04 }, +#endif +#ifdef PIN_PA05 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA05), (mp_obj_t)&pin_PA05 }, +#endif +#ifdef PIN_PA06 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA06), (mp_obj_t)&pin_PA06 }, +#endif +#ifdef PIN_PA07 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA07), (mp_obj_t)&pin_PA07 }, +#endif +#ifdef PIN_PA08 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA08), (mp_obj_t)&pin_PA08 }, +#endif +#ifdef PIN_PA09 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA09), (mp_obj_t)&pin_PA09 }, +#endif +#ifdef PIN_PA10 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA10), (mp_obj_t)&pin_PA10 }, +#endif +#ifdef PIN_PA11 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA11), (mp_obj_t)&pin_PA11 }, +#endif +#ifdef PIN_PB10 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB10), (mp_obj_t)&pin_PB10 }, +#endif +#ifdef PIN_PB11 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB11), (mp_obj_t)&pin_PB11 }, +#endif +#ifdef PIN_PB12 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB12), (mp_obj_t)&pin_PB12 }, +#endif +#ifdef PIN_PB13 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB13), (mp_obj_t)&pin_PB13 }, +#endif +#ifdef PIN_PB14 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB14), (mp_obj_t)&pin_PB14 }, +#endif + +// Second page. +#ifdef PIN_PB15 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB15), (mp_obj_t)&pin_PB15 }, +#endif +#ifdef PIN_PA12 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA12), (mp_obj_t)&pin_PA12 }, +#endif +#ifdef PIN_PA13 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA13), (mp_obj_t)&pin_PA13 }, +#endif +#ifdef PIN_PA14 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA14), (mp_obj_t)&pin_PA14 }, +#endif +#ifdef PIN_PA15 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA15), (mp_obj_t)&pin_PA15 }, +#endif +#ifdef PIN_PA16 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA16), (mp_obj_t)&pin_PA16 }, +#endif +#ifdef PIN_PA17 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA17), (mp_obj_t)&pin_PA17 }, +#endif +#ifdef PIN_PA18 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA18), (mp_obj_t)&pin_PA18 }, +#endif +#ifdef PIN_PA19 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA19), (mp_obj_t)&pin_PA19 }, +#endif +#ifdef PIN_PB16 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB16), (mp_obj_t)&pin_PB16 }, +#endif +#ifdef PIN_PB17 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB17), (mp_obj_t)&pin_PB17 }, +#endif +#ifdef PIN_PA20 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA20), (mp_obj_t)&pin_PA20 }, +#endif +#ifdef PIN_PA21 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA21), (mp_obj_t)&pin_PA21 }, +#endif +#ifdef PIN_PA22 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA22), (mp_obj_t)&pin_PA22 }, +#endif +#ifdef PIN_PA23 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA23), (mp_obj_t)&pin_PA23 }, +#endif +#ifdef PIN_PA24 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA24), (mp_obj_t)&pin_PA24 }, +#endif +#ifdef PIN_PA25 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA25), (mp_obj_t)&pin_PA25 }, +#endif +#ifdef PIN_PB22 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB22), (mp_obj_t)&pin_PB22 }, +#endif +#ifdef PIN_PB23 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB23), (mp_obj_t)&pin_PB23 }, +#endif +#ifdef PIN_PA27 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA27), (mp_obj_t)&pin_PA27 }, +#endif +#ifdef PIN_PA28 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA28), (mp_obj_t)&pin_PA28 }, +#endif +#ifdef PIN_PA30 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA30), (mp_obj_t)&pin_PA30 }, +#endif +#ifdef PIN_PA31 + { MP_OBJ_NEW_QSTR(MP_QSTR_PA31), (mp_obj_t)&pin_PA31 }, +#endif +#ifdef PIN_PB30 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB30), (mp_obj_t)&pin_PB30 }, +#endif +#ifdef PIN_PB31 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB31), (mp_obj_t)&pin_PB31 }, +#endif +#ifdef PIN_PB00 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB00), (mp_obj_t)&pin_PB00 }, +#endif +#ifdef PIN_PB01 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB01), (mp_obj_t)&pin_PB01 }, +#endif +#ifdef PIN_PB02 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB02), (mp_obj_t)&pin_PB02 }, +#endif +#ifdef PIN_PB03 + { MP_OBJ_NEW_QSTR(MP_QSTR_PB03), (mp_obj_t)&pin_PB03 } +#endif +}; +MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table); diff --git a/atmel-samd/common-hal/modules/machine_types.h b/atmel-samd/common-hal/microcontroller/types.h similarity index 61% rename from atmel-samd/common-hal/modules/machine_types.h rename to atmel-samd/common-hal/microcontroller/types.h index 73150640f0..48ef7346b1 100644 --- a/atmel-samd/common-hal/modules/machine_types.h +++ b/atmel-samd/common-hal/microcontroller/types.h @@ -24,25 +24,18 @@ * THE SOFTWARE. */ -// Machine is the HAL for low-level, hardware accelerated functions. It is not -// meant to simplify APIs, its only meant to unify them so that other modules -// do not require port specific logic. -// -// This file defines core data structures for machine classes. They are port -// specific and passed through the Python layer untouched. - -#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_API_MACHINE_TYPES_H__ -#define __MICROPY_INCLUDED_ATMEL_SAMD_API_MACHINE_TYPES_H__ +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__ // Don't reorder these includes because they are dependencies of adc_feature.h. // They should really be included by adc_feature.h. #include "compiler.h" #include "asf/sam0/drivers/system/clock/gclk.h" #include "asf/sam0/utils/cmsis/samd21/include/component/adc.h" -#include "asf/sam0/drivers/adc/adc_sam_d_r/adc_feature.h" +#include "asf/sam0/drivers/adc/adc_sam_d_r/adc_feature.h" // for adc_positive_input -#include "asf/sam0/drivers/sercom/i2c/i2c_master.h" -#include "asf/sam0/drivers/sercom/spi/spi.h" +#include "asf/sam0/drivers/tc/tc.h" +#include "asf/sam0/drivers/tcc/tcc.h" #include "py/obj.h" @@ -63,24 +56,14 @@ typedef struct { #define NUM_SERCOMS_PER_PIN 2 typedef struct { - mp_obj_base_t base; - qstr name; - uint32_t pin; - bool has_adc; - enum adc_positive_input adc_input; - pin_timer_t primary_timer; - pin_timer_t secondary_timer; - pin_sercom_t sercom[NUM_SERCOMS_PER_PIN]; -} pin_obj_t; + mp_obj_base_t base; + qstr name; + uint32_t pin; + bool has_adc; + enum adc_positive_input adc_input; + pin_timer_t primary_timer; + pin_timer_t secondary_timer; + pin_sercom_t sercom[NUM_SERCOMS_PER_PIN]; +} mcu_pin_obj_t; -typedef struct _machine_i2c_obj_t { - mp_obj_base_t base; - struct i2c_master_module i2c_master_instance; -} machine_i2c_obj_t; - -typedef struct _machine_spi_obj_t { - mp_obj_base_t base; - struct spi_module spi_master_instance; -} machine_spi_obj_t; - -#endif // __MICROPY_INCLUDED_ATMEL_SAMD_API_MACHINE_TYPES_H__ +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__ diff --git a/atmel-samd/common-hal/modules/machine.c b/atmel-samd/common-hal/modules/machine.c deleted file mode 100644 index 70ca0a67a2..0000000000 --- a/atmel-samd/common-hal/modules/machine.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Scott Shawcroft - * - * 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. - */ - - // This file contains all of the port specific HAL functions for the machine - // module. - -#include "shared-bindings/modules/machine.h" -#include "py/nlr.h" - -#include "asf/sam0/drivers/sercom/i2c/i2c_master.h" - -// We use ENABLE registers below we don't want to treat as a macro. -#undef ENABLE - -// Number of times to try to send packet if failed. -#define TIMEOUT 1 - -void mp_hal_i2c_construct(machine_i2c_obj_t *self, const pin_obj_t* scl, - const pin_obj_t* sda, uint32_t freq) { - struct i2c_master_config config_i2c_master; - i2c_master_get_config_defaults(&config_i2c_master); - // Struct takes the argument in Khz not Hz. - config_i2c_master.baud_rate = freq / 1000; - Sercom* sercom = NULL; - uint32_t sda_pinmux = 0; - uint32_t scl_pinmux = 0; - for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { - Sercom* potential_sercom = sda->sercom[i].sercom; - if (potential_sercom == NULL || - potential_sercom->I2CM.CTRLA.bit.ENABLE != 0 || - sda->sercom[i].pad != 0) { - continue; - } - sda_pinmux = sda->sercom[i].pinmux; - for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - if (potential_sercom == scl->sercom[j].sercom && - scl->sercom[j].pad == 1) { - scl_pinmux = scl->sercom[j].pinmux; - sercom = potential_sercom; - break; - } - } - if (sercom != NULL) { - break; - } - } - if (sercom == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, - "No hardware support available with those pins.")); - } - - config_i2c_master.pinmux_pad0 = sda_pinmux; // SDA - config_i2c_master.pinmux_pad1 = scl_pinmux; // SCL - config_i2c_master.buffer_timeout = 10000; - - enum status_code status = i2c_master_init(&self->i2c_master_instance, - sercom, &config_i2c_master); - if (status != STATUS_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus init error")); - } - - i2c_master_enable(&self->i2c_master_instance); -} - -void mp_hal_i2c_deinit(machine_i2c_obj_t *self) { - i2c_master_disable(&self->i2c_master_instance); -} - -void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, - size_t len) { - struct i2c_master_packet packet = { - .address = addr, - .data_length = len, - .data = data, - .ten_bit_address = false, - .high_speed = false, - .hs_master_code = 0x0, - }; - - uint16_t timeout = 0; - enum status_code status = STATUS_BUSY; - while (status != STATUS_OK) { - status = i2c_master_write_packet_wait(&self->i2c_master_instance, - &packet); - /* Increment timeout counter and check if timed out. */ - if (timeout++ == TIMEOUT) { - break; - } - } - if (status != STATUS_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); - } -} - -bool mp_hal_i2c_probe(machine_i2c_obj_t *self, uint8_t addr) { - uint8_t buf; - struct i2c_master_packet packet = { - .address = addr, - .data_length = 0, - .data = &buf, - .ten_bit_address = false, - .high_speed = false, - .hs_master_code = 0x0, - }; - - enum status_code status = i2c_master_write_packet_wait( - &self->i2c_master_instance, &packet); - return status == STATUS_OK; -} - -void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, - size_t len) { - struct i2c_master_packet packet = { - .address = addr, - .data_length = len, - .data = data, - .ten_bit_address = false, - .high_speed = false, - .hs_master_code = 0x0, - }; - - uint16_t timeout = 0; - enum status_code status = STATUS_BUSY; - while (status != STATUS_OK) { - status = i2c_master_read_packet_wait(&self->i2c_master_instance, - &packet); - /* Increment timeout counter and check if timed out. */ - if (timeout++ == TIMEOUT) { - break; - } - } - if (status != STATUS_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); - } -} - -void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr, - uint16_t memaddr, const uint8_t *src, size_t len) { - uint8_t buffer[len+1]; - buffer[0] = (uint8_t) memaddr; - for (int i = 0; i < len; i++) { - buffer[i+1] = src[i]; - } - struct i2c_master_packet packet = { - .address = addr, - .data_length = len + 1, - .data = buffer, - .ten_bit_address = false, - .high_speed = false, - .hs_master_code = 0x0, - }; - - uint16_t timeout = 0; - enum status_code status = STATUS_BUSY; - while (status != STATUS_OK) { - status = i2c_master_write_packet_wait(&self->i2c_master_instance, - &packet); - /* Increment timeout counter and check if timed out. */ - if (timeout++ == TIMEOUT) { - break; - } - } - if (status != STATUS_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); - } -} - -void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr, uint8_t *dest, size_t len) { - // Write the memory address. - struct i2c_master_packet packet = { - .address = addr, - .data_length = 1, - .data = (uint8_t *)&memaddr, - .ten_bit_address = false, - .high_speed = false, - .hs_master_code = 0x0, - }; - uint16_t timeout = 0; - enum status_code status = STATUS_BUSY; - while (status != STATUS_OK) { - status = i2c_master_write_packet_wait_no_stop( - &self->i2c_master_instance, &packet); - /* Increment timeout counter and check if timed out. */ - if (timeout++ == TIMEOUT) { - break; - } - } - - if (status != STATUS_OK) { - i2c_master_send_stop(&self->i2c_master_instance); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); - } - - // i2c_read will do a repeated start, and then read the I2C memory - mp_hal_i2c_read(self, addr, dest, len); - return; -} - -void mp_hal_spi_construct(machine_spi_obj_t *self, const pin_obj_t * clock, - const pin_obj_t * mosi, const pin_obj_t * miso, - uint32_t baudrate) { - struct spi_config config_spi_master; - spi_get_config_defaults(&config_spi_master); - - Sercom* sercom = NULL; - uint32_t clock_pinmux = 0; - uint32_t mosi_pinmux = 0; - uint32_t miso_pinmux = 0; - uint8_t clock_pad = 0; - uint8_t mosi_pad = 0; - uint8_t miso_pad = 0; - for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { - Sercom* potential_sercom = clock->sercom[i].sercom; - if (potential_sercom == NULL || - potential_sercom->SPI.CTRLA.bit.ENABLE != 0) { - continue; - } - clock_pinmux = clock->sercom[i].pinmux; - clock_pad = clock->sercom[i].pad; - for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { - mosi_pinmux = mosi->sercom[j].pinmux; - mosi_pad = mosi->sercom[j].pad; - for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) { - if (potential_sercom == miso->sercom[k].sercom) { - miso_pinmux = miso->sercom[k].pinmux; - miso_pad = miso->sercom[k].pad; - sercom = potential_sercom; - break; - } - } - if (sercom != NULL) { - break; - } - } - if (sercom != NULL) { - break; - } - } - if (sercom == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, - "No hardware support available with those pins.")); - } - - // Depends on where MOSI and CLK are. - uint8_t dopo = 8; - if (clock_pad == 1) { - if (mosi_pad == 0) { - dopo = 0; - } else if (mosi_pad == 3) { - dopo = 2; - } - } else if (clock_pad == 3) { - if (mosi_pad == 0) { - dopo = 3; - } else if (mosi_pad == 2) { - dopo = 1; - } - } - if (dopo == 8) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "SPI MOSI and clock pins incompatible.")); - } - - config_spi_master.mux_setting = (dopo << SERCOM_SPI_CTRLA_DOPO_Pos) | - (miso_pad << SERCOM_SPI_CTRLA_DIPO_Pos); - - // Map pad to pinmux through a short array. - uint32_t *pinmuxes[4] = {&config_spi_master.pinmux_pad0, - &config_spi_master.pinmux_pad1, - &config_spi_master.pinmux_pad2, - &config_spi_master.pinmux_pad3}; - *pinmuxes[clock_pad] = clock_pinmux; - *pinmuxes[mosi_pad] = mosi_pinmux; - *pinmuxes[miso_pad] = miso_pinmux; - - config_spi_master.mode_specific.master.baudrate = baudrate; - - spi_init(&self->spi_master_instance, sercom, &config_spi_master); - - spi_enable(&self->spi_master_instance); -} - -void mp_hal_spi_deinit(machine_spi_obj_t *self) { - spi_disable(&self->spi_master_instance); -} - -void mp_hal_spi_transfer(machine_spi_obj_t *self, size_t len, const uint8_t *src, - uint8_t *dest) { - // TODO(tannewt): Don't cast away the const. Change ASF to respect it instead. - enum status_code status = spi_transceive_buffer_wait( - &self->spi_master_instance, (uint8_t *) src, dest, len); - if (status != STATUS_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "SPI bus error")); - } -} diff --git a/atmel-samd/common-hal/nativeio/AnalogIn.c b/atmel-samd/common-hal/nativeio/AnalogIn.c new file mode 100644 index 0000000000..faf63265f8 --- /dev/null +++ b/atmel-samd/common-hal/nativeio/AnalogIn.c @@ -0,0 +1,76 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/binary.h" +#include "py/mphal.h" +#include "shared-bindings/nativeio/AnalogIn.h" + +#include "asf/sam0/drivers/adc/adc.h" + +void common_hal_nativeio_analogin_construct(nativeio_analogin_obj_t* self, + const mcu_pin_obj_t *pin) { + if (!pin->has_adc) { + // No ADC function on that pin + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %q does not have ADC capabilities", pin->name)); + } + + self->pin = pin; + + struct adc_config config_adc; + adc_get_config_defaults(&config_adc); + + config_adc.positive_input = self->pin->adc_input; + config_adc.resolution = ADC_RESOLUTION_CUSTOM; + config_adc.accumulate_samples = ADC_ACCUMULATE_SAMPLES_16; + config_adc.divide_result = ADC_DIVIDE_RESULT_16; + config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV128; + + adc_init(&self->adc_instance, ADC, &config_adc); +} + +// TODO(tannewt): Don't turn it all on just for one read. This simplifies +// handling of reading multiple inputs and surviving sleep though so for now its +// ok. +uint16_t common_hal_nativeio_analogin_get_value(nativeio_analogin_obj_t *self) { + adc_enable(&self->adc_instance); + adc_start_conversion(&self->adc_instance); + + uint16_t data; + enum status_code status = adc_read(&self->adc_instance, &data); + while (status == STATUS_BUSY) { + status = adc_read(&self->adc_instance, &data); + } + if (status == STATUS_ERR_OVERFLOW) { + // TODO(tannewt): Throw an error. + } + + adc_disable(&self->adc_instance); + return data; +} diff --git a/atmel-samd/common-hal/nativeio/AnalogOut.c b/atmel-samd/common-hal/nativeio/AnalogOut.c new file mode 100644 index 0000000000..5540cb37d6 --- /dev/null +++ b/atmel-samd/common-hal/nativeio/AnalogOut.c @@ -0,0 +1,69 @@ +/* + * 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 +#include + +#include "py/runtime.h" + +#include "shared-bindings/nativeio/AnalogOut.h" + +#include "asf/sam0/drivers/dac/dac.h" + +void common_hal_nativeio_analogout_construct(nativeio_analogout_obj_t* self, + const mcu_pin_obj_t *pin) { + if (pin->pin != PIN_PA02) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "DAC only supported on pin PA02.")); + return; + } + struct dac_config config_dac; + dac_get_config_defaults(&config_dac); + config_dac.reference = DAC_REFERENCE_AVCC; + enum status_code status = dac_init(&self->dac_instance, DAC, &config_dac); + if (status != STATUS_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "DAC init failed.")); + return; + } + + struct dac_chan_config config_analogout_chan; + dac_chan_get_config_defaults(&config_analogout_chan); + dac_chan_set_config(&self->dac_instance, DAC_CHANNEL_0, &config_analogout_chan); + dac_chan_enable(&self->dac_instance, DAC_CHANNEL_0); + + dac_enable(&self->dac_instance); +} + +void common_hal_nativeio_analogout_deinit(nativeio_analogout_obj_t *self) { + dac_disable(&self->dac_instance); + dac_chan_disable(&self->dac_instance, DAC_CHANNEL_0); +} + +void common_hal_nativeio_analogout_set_value(nativeio_analogout_obj_t *self, + uint16_t value) { + dac_chan_write(&self->dac_instance, DAC_CHANNEL_0, value); +} diff --git a/atmel-samd/common-hal/nativeio/DigitalInOut.c b/atmel-samd/common-hal/nativeio/DigitalInOut.c new file mode 100644 index 0000000000..119832ff69 --- /dev/null +++ b/atmel-samd/common-hal/nativeio/DigitalInOut.c @@ -0,0 +1,186 @@ +/* + * 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 +#include + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "shared-bindings/nativeio/DigitalInOut.h" + +#include "asf/sam0/drivers/port/port.h" +#include "asf/sam0/drivers/system/pinmux/pinmux.h" + +digitalinout_result_t common_hal_nativeio_digitalinout_construct( + nativeio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin) { + self->pin = pin; + + struct port_config pin_conf; + port_get_config_defaults(&pin_conf); + + pin_conf.direction = PORT_PIN_DIR_INPUT; + pin_conf.input_pull = PORT_PIN_PULL_NONE; + port_pin_set_config(self->pin->pin, &pin_conf); + return DIGITALINOUT_OK; +} + +void common_hal_nativeio_digitalinout_deinit(nativeio_digitalinout_obj_t* self) { + struct port_config pin_conf; + port_get_config_defaults(&pin_conf); + + pin_conf.powersave = true; + port_pin_set_config(self->pin->pin, &pin_conf); +} + +void common_hal_nativeio_digitalinout_switch_to_input( + nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull) { + self->output = false; + + common_hal_nativeio_digitalinout_set_pull(self, pull); +} + +void common_hal_nativeio_digitalinout_switch_to_output( + nativeio_digitalinout_obj_t* self, bool value, + enum digitalinout_drive_mode_t drive_mode) { + struct port_config pin_conf; + port_get_config_defaults(&pin_conf); + + pin_conf.direction = PORT_PIN_DIR_INPUT; + pin_conf.input_pull = PORT_PIN_PULL_NONE; + port_pin_set_config(self->pin->pin, &pin_conf); + + self->output = true; + self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; + common_hal_nativeio_digitalinout_set_value(self, value); +} + +enum digitalinout_direction_t common_hal_nativeio_digitalinout_get_direction( + nativeio_digitalinout_obj_t* self) { + return self->output? DIRECTION_OUT : DIRECTION_IN; +} + +void common_hal_nativeio_digitalinout_set_value( + nativeio_digitalinout_obj_t* self, bool value) { + uint32_t pin = self->pin->pin; + PortGroup *const port_base = port_get_group_from_gpio_pin(pin); + uint32_t pin_mask = (1UL << (pin % 32)); + + /* Set the pin to high or low atomically based on the requested level */ + if (value) { + if (self->open_drain) { + port_base->DIRCLR.reg = pin_mask; + } else { + port_base->DIRSET.reg = pin_mask; + port_base->OUTSET.reg = pin_mask; + } + } else { + if (!self->open_drain) { + port_base->DIRSET.reg = pin_mask; + } + port_base->OUTCLR.reg = pin_mask; + } +} + +bool common_hal_nativeio_digitalinout_get_value( + nativeio_digitalinout_obj_t* self) { + uint32_t pin = self->pin->pin; + PortGroup *const port_base = port_get_group_from_gpio_pin(pin); + uint32_t pin_mask = (1UL << (pin % 32)); + if (!self->output) { + return (port_base->IN.reg & pin_mask); + } else { + if (self->open_drain && (port_base->DIR.reg & pin_mask) == 0) { + return true; + } else { + return (port_base->OUT.reg & pin_mask); + } + } +} + +void common_hal_nativeio_digitalinout_set_drive_mode( + nativeio_digitalinout_obj_t* self, + enum digitalinout_drive_mode_t drive_mode) { + bool value = common_hal_nativeio_digitalinout_get_value(self); + self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; + // True is implemented differently between modes so reset the value to make + // sure its correct for the new mode. + if (value) { + common_hal_nativeio_digitalinout_set_value(self, value); + } +} + +enum digitalinout_drive_mode_t common_hal_nativeio_digitalinout_get_drive_mode( + nativeio_digitalinout_obj_t* self) { + if (self->open_drain) { + return DRIVE_MODE_OPEN_DRAIN; + } else { + return DRIVE_MODE_PUSH_PULL; + } +} + +void common_hal_nativeio_digitalinout_set_pull( + nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull) { + enum port_pin_pull asf_pull = PORT_PIN_PULL_NONE; + switch (pull) { + case PULL_UP: + asf_pull = PORT_PIN_PULL_UP; + break; + case PULL_DOWN: + asf_pull = PORT_PIN_PULL_DOWN; + break; + case PULL_NONE: + default: + break; + } + struct port_config pin_conf; + port_get_config_defaults(&pin_conf); + + pin_conf.direction = PORT_PIN_DIR_INPUT; + pin_conf.input_pull = asf_pull; + port_pin_set_config(self->pin->pin, &pin_conf); +} + +enum digitalinout_pull_t common_hal_nativeio_digitalinout_get_pull( + nativeio_digitalinout_obj_t* self) { + uint32_t pin = self->pin->pin; + PortGroup *const port_base = port_get_group_from_gpio_pin(pin); + uint32_t pin_mask = (1UL << (pin % 32)); + if (self->output) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Cannot get pull while in output mode.")); + return PULL_NONE; + } else { + if (port_base->PINCFG[pin % 32].bit.PULLEN != 0) { + return PULL_NONE; + } if ((port_base->OUT.reg & pin_mask) > 0) { + return PULL_UP; + } else { + return PULL_DOWN; + } + } +} diff --git a/atmel-samd/common-hal/nativeio/I2C.c b/atmel-samd/common-hal/nativeio/I2C.c new file mode 100644 index 0000000000..9eb2361fb8 --- /dev/null +++ b/atmel-samd/common-hal/nativeio/I2C.c @@ -0,0 +1,159 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + + // This file contains all of the port specific HAL functions for the machine + // module. + +#include "shared-bindings/nativeio/I2C.h" +#include "py/nlr.h" + +#include "asf/sam0/drivers/sercom/i2c/i2c_master.h" + +// We use ENABLE registers below we don't want to treat as a macro. +#undef ENABLE + +// Number of times to try to send packet if failed. +#define TIMEOUT 1 + +void common_hal_nativeio_i2c_construct(nativeio_i2c_obj_t *self, + const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t freq) { + struct i2c_master_config config_i2c_master; + i2c_master_get_config_defaults(&config_i2c_master); + // Struct takes the argument in Khz not Hz. + config_i2c_master.baud_rate = freq / 1000; + Sercom* sercom = NULL; + uint32_t sda_pinmux = 0; + uint32_t scl_pinmux = 0; + for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { + Sercom* potential_sercom = sda->sercom[i].sercom; + if (potential_sercom == NULL || + potential_sercom->I2CM.CTRLA.bit.ENABLE != 0 || + sda->sercom[i].pad != 0) { + continue; + } + sda_pinmux = sda->sercom[i].pinmux; + for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { + if (potential_sercom == scl->sercom[j].sercom && + scl->sercom[j].pad == 1) { + scl_pinmux = scl->sercom[j].pinmux; + sercom = potential_sercom; + break; + } + } + if (sercom != NULL) { + break; + } + } + if (sercom == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "No hardware support available with those pins.")); + } + + config_i2c_master.pinmux_pad0 = sda_pinmux; // SDA + config_i2c_master.pinmux_pad1 = scl_pinmux; // SCL + config_i2c_master.buffer_timeout = 10000; + + enum status_code status = i2c_master_init(&self->i2c_master_instance, + sercom, &config_i2c_master); + if (status != STATUS_OK) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus init error")); + } + + i2c_master_enable(&self->i2c_master_instance); +} + +void common_hal_nativeio_i2c_deinit(nativeio_i2c_obj_t *self) { + i2c_master_disable(&self->i2c_master_instance); +} + +bool common_hal_nativeio_i2c_probe(nativeio_i2c_obj_t *self, uint8_t addr) { + uint8_t buf; + struct i2c_master_packet packet = { + .address = addr, + .data_length = 0, + .data = &buf, + .ten_bit_address = false, + .high_speed = false, + .hs_master_code = 0x0, + }; + + enum status_code status = i2c_master_write_packet_wait( + &self->i2c_master_instance, &packet); + return status == STATUS_OK; +} + +bool common_hal_nativeio_i2c_write(nativeio_i2c_obj_t *self, uint16_t addr, + const uint8_t *data, size_t len, bool transmit_stop_bit) { + struct i2c_master_packet packet = { + .address = addr, + .data_length = len, + .data = (uint8_t *) data, + .ten_bit_address = false, + .high_speed = false, + .hs_master_code = 0x0, + }; + + uint16_t timeout = 0; + enum status_code status = STATUS_BUSY; + while (status != STATUS_OK) { + if (transmit_stop_bit) { + status = i2c_master_write_packet_wait(&self->i2c_master_instance, + &packet); + } else { + status = i2c_master_write_packet_wait_no_stop( + &self->i2c_master_instance, &packet); + } + /* Increment timeout counter and check if timed out. */ + if (timeout++ == TIMEOUT) { + break; + } + } + return status == STATUS_OK; +} + +bool common_hal_nativeio_i2c_read(nativeio_i2c_obj_t *self, uint16_t addr, + uint8_t *data, size_t len) { + struct i2c_master_packet packet = { + .address = addr, + .data_length = len, + .data = data, + .ten_bit_address = false, + .high_speed = false, + .hs_master_code = 0x0, + }; + + uint16_t timeout = 0; + enum status_code status = STATUS_BUSY; + while (status != STATUS_OK) { + status = i2c_master_read_packet_wait(&self->i2c_master_instance, + &packet); + /* Increment timeout counter and check if timed out. */ + if (timeout++ == TIMEOUT) { + break; + } + } + return status == STATUS_OK; +} diff --git a/atmel-samd/common-hal/nativeio/PWMOut.c b/atmel-samd/common-hal/nativeio/PWMOut.c new file mode 100644 index 0000000000..a444ba864e --- /dev/null +++ b/atmel-samd/common-hal/nativeio/PWMOut.c @@ -0,0 +1,114 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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 + +#include "py/runtime.h" +#include "shared-bindings/nativeio/PWMOut.h" + +void common_hal_nativeio_pwmout_construct(nativeio_pwmout_obj_t* self, const mcu_pin_obj_t* pin, uint16_t duty) { + self->pin = pin; + self->using_primary_timer = true; + + if (pin->primary_timer.tc == 0 && pin->primary_timer.tcc == 0 && + pin->secondary_timer.tc == 0 && pin->secondary_timer.tcc == 0) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "PWM not supported on pin %q", self->pin->name)); + } + + // TODO(tannewt): Support output on multiple timer channels at once. + const pin_timer_t* t = &pin->primary_timer; + if (t->tcc != 0) { + struct tcc_config config_tcc; + tcc_get_config_defaults(&config_tcc, t->tcc); + + config_tcc.counter.clock_prescaler = TCC_CLOCK_PRESCALER_DIV256; + config_tcc.counter.period = 0xFF; + config_tcc.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM; + config_tcc.compare.match[t->channel] = duty; + + config_tcc.pins.enable_wave_out_pin[t->wave_output] = true; + config_tcc.pins.wave_out_pin[t->wave_output] = t->pin; + config_tcc.pins.wave_out_pin_mux[t->wave_output] = t->mux; + + tcc_init(&self->tcc_instance, t->tcc, &config_tcc); + + tcc_enable(&self->tcc_instance); + } else { + struct tc_config config_tc; + tc_get_config_defaults(&config_tc); + + config_tc.counter_size = TC_COUNTER_SIZE_8BIT; + config_tc.wave_generation = TC_WAVE_GENERATION_NORMAL_PWM; + config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV256; + config_tc.counter_8_bit.period = 0xff; + config_tc.counter_8_bit.compare_capture_channel[t->channel] = duty; + + config_tc.pwm_channel[t->wave_output].enabled = true; + config_tc.pwm_channel[t->wave_output].pin_out = t->pin; + config_tc.pwm_channel[t->wave_output].pin_mux = t->mux; + + tc_init(&self->tc_instance, t->tc, &config_tc); + + tc_enable(&self->tc_instance); + } +} + +extern void common_hal_nativeio_pwmout_deinit(nativeio_pwmout_obj_t* self) { + const pin_timer_t* t = &self->pin->primary_timer; + if (!self->using_primary_timer) { + t = &self->pin->secondary_timer; + } + if (t->tcc != 0) { + tcc_disable(&self->tcc_instance); + } else { + tc_disable(&self->tc_instance); + } +} + +extern void common_hal_nativeio_pwmout_set_duty_cycle(nativeio_pwmout_obj_t* self, uint16_t duty) { + const pin_timer_t* t = &self->pin->primary_timer; + if (!self->using_primary_timer) { + t = &self->pin->secondary_timer; + } + if (t->tcc != 0) { + tcc_set_compare_value(&self->tcc_instance, t->channel, duty); + } else { + tc_set_compare_value(&self->tc_instance, t->channel, duty); + } +} + +uint16_t common_hal_nativeio_pwmout_get_duty_cycle(nativeio_pwmout_obj_t* self) { + const pin_timer_t* t = &self->pin->primary_timer; + if (!self->using_primary_timer) { + t = &self->pin->secondary_timer; + } + if (t->tcc != 0) { + return tcc_get_capture_value(&self->tcc_instance, t->channel); + } else { + return tc_get_capture_value(&self->tc_instance, t->channel); + } +} diff --git a/atmel-samd/common-hal/nativeio/SPI.c b/atmel-samd/common-hal/nativeio/SPI.c new file mode 100644 index 0000000000..7600766f77 --- /dev/null +++ b/atmel-samd/common-hal/nativeio/SPI.c @@ -0,0 +1,143 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + + // This file contains all of the port specific HAL functions for the machine + // module. + +#include "shared-bindings/nativeio/SPI.h" +#include "py/nlr.h" + +// We use ENABLE registers below we don't want to treat as a macro. +#undef ENABLE + +// Number of times to try to send packet if failed. +#define TIMEOUT 1 + +void common_hal_nativeio_spi_construct(nativeio_spi_obj_t *self, + const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, + const mcu_pin_obj_t * miso, uint32_t baudrate) { + struct spi_config config_spi_master; + spi_get_config_defaults(&config_spi_master); + + Sercom* sercom = NULL; + uint32_t clock_pinmux = 0; + uint32_t mosi_pinmux = 0; + uint32_t miso_pinmux = 0; + uint8_t clock_pad = 0; + uint8_t mosi_pad = 0; + uint8_t miso_pad = 0; + for (int i = 0; i < NUM_SERCOMS_PER_PIN; i++) { + Sercom* potential_sercom = clock->sercom[i].sercom; + if (potential_sercom == NULL || + potential_sercom->SPI.CTRLA.bit.ENABLE != 0) { + continue; + } + clock_pinmux = clock->sercom[i].pinmux; + clock_pad = clock->sercom[i].pad; + for (int j = 0; j < NUM_SERCOMS_PER_PIN; j++) { + mosi_pinmux = mosi->sercom[j].pinmux; + mosi_pad = mosi->sercom[j].pad; + for (int k = 0; k < NUM_SERCOMS_PER_PIN; k++) { + if (potential_sercom == miso->sercom[k].sercom) { + miso_pinmux = miso->sercom[k].pinmux; + miso_pad = miso->sercom[k].pad; + sercom = potential_sercom; + break; + } + } + if (sercom != NULL) { + break; + } + } + if (sercom != NULL) { + break; + } + } + if (sercom == NULL) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "No hardware support available with those pins.")); + } + + // Depends on where MOSI and CLK are. + uint8_t dopo = 8; + if (clock_pad == 1) { + if (mosi_pad == 0) { + dopo = 0; + } else if (mosi_pad == 3) { + dopo = 2; + } + } else if (clock_pad == 3) { + if (mosi_pad == 0) { + dopo = 3; + } else if (mosi_pad == 2) { + dopo = 1; + } + } + if (dopo == 8) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "SPI MOSI and clock pins incompatible.")); + } + + config_spi_master.mux_setting = (dopo << SERCOM_SPI_CTRLA_DOPO_Pos) | + (miso_pad << SERCOM_SPI_CTRLA_DIPO_Pos); + + // Map pad to pinmux through a short array. + uint32_t *pinmuxes[4] = {&config_spi_master.pinmux_pad0, + &config_spi_master.pinmux_pad1, + &config_spi_master.pinmux_pad2, + &config_spi_master.pinmux_pad3}; + *pinmuxes[clock_pad] = clock_pinmux; + *pinmuxes[mosi_pad] = mosi_pinmux; + *pinmuxes[miso_pad] = miso_pinmux; + + config_spi_master.mode_specific.master.baudrate = baudrate; + + spi_init(&self->spi_master_instance, sercom, &config_spi_master); + + spi_enable(&self->spi_master_instance); +} + +void common_hal_nativeio_spi_deinit(nativeio_spi_obj_t *self) { + spi_disable(&self->spi_master_instance); +} + +bool common_hal_nativeio_spi_write(nativeio_spi_obj_t *self, + const uint8_t *data, size_t len) { + enum status_code status = spi_write_buffer_wait( + &self->spi_master_instance, + data, + len); + return status == STATUS_OK; +} + +bool common_hal_nativeio_spi_read(nativeio_spi_obj_t *self, + uint8_t *data, size_t len) { + enum status_code status = spi_read_buffer_wait( + &self->spi_master_instance, + data, + len, + 0); + return status == STATUS_OK; +} diff --git a/atmel-samd/common-hal/nativeio/__init__.c b/atmel-samd/common-hal/nativeio/__init__.c new file mode 100644 index 0000000000..e0ec8acfb1 --- /dev/null +++ b/atmel-samd/common-hal/nativeio/__init__.c @@ -0,0 +1 @@ +// No nativeio module functions. diff --git a/atmel-samd/common-hal/nativeio/types.h b/atmel-samd/common-hal/nativeio/types.h new file mode 100644 index 0000000000..0842262bd0 --- /dev/null +++ b/atmel-samd/common-hal/nativeio/types.h @@ -0,0 +1,86 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// This defines the types used to underly the standard nativeio Python objects. +// The shared API is defined in terms of these types. + +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__ + +#include "common-hal/microcontroller/types.h" + +// Don't reorder these includes because they are dependencies of adc_feature.h. +// They should really be included by adc_feature.h. +#include +#include "asf/sam0/drivers/system/clock/gclk.h" +#include "asf/sam0/utils/cmsis/samd21/include/component/adc.h" +#include "asf/sam0/drivers/adc/adc_sam_d_r/adc_feature.h" + +#include "asf/sam0/drivers/dac/dac.h" +#include "asf/sam0/drivers/sercom/i2c/i2c_master.h" +#include "asf/sam0/drivers/sercom/spi/spi.h" +#include "asf/sam0/drivers/tc/tc.h" +#include "asf/sam0/drivers/tcc/tcc.h" + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t * pin; + struct adc_module adc_instance; +} nativeio_analogin_obj_t; + +typedef struct { + mp_obj_base_t base; + struct dac_module dac_instance; +} nativeio_analogout_obj_t; + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t * pin; + bool output; + bool open_drain; +} nativeio_digitalinout_obj_t; + +typedef struct { + mp_obj_base_t base; + struct i2c_master_module i2c_master_instance; +} nativeio_i2c_obj_t; + +typedef struct _machine_spi_obj_t { + mp_obj_base_t base; + struct spi_module spi_master_instance; +} nativeio_spi_obj_t; + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t *pin; + bool using_primary_timer; + struct tc_module tc_instance; + struct tcc_module tcc_instance; +} nativeio_pwmout_obj_t; + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__ diff --git a/atmel-samd/common-hal/neopixel_write/__init__.c b/atmel-samd/common-hal/neopixel_write/__init__.c new file mode 100644 index 0000000000..f720c45181 --- /dev/null +++ b/atmel-samd/common-hal/neopixel_write/__init__.c @@ -0,0 +1,116 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 "mphalport.h" + +#include "shared-bindings/neopixel_write/__init__.h" + +#include "asf/common2/services/delay/delay.h" + +void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes, bool is800KHz) { + // This is adapted directly from the Adafruit NeoPixel library SAMD21G18A code: + // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp + uint8_t *ptr, *end, p, bitMask; + uint32_t pinMask; + PortGroup* port; + + // Turn off interrupts of any kind during timing-sensitive code. + mp_hal_disable_all_interrupts(); + + uint32_t pin = digitalinout->pin->pin; + port = port_get_group_from_gpio_pin(pin); + pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code. + ptr = pixels; + end = ptr + numBytes; + p = *ptr++; + bitMask = 0x80; + + volatile uint32_t *set = &(port->OUTSET.reg), + *clr = &(port->OUTCLR.reg); + + if(is800KHz) { + for(;;) { + *set = pinMask; + asm("nop; nop;"); + if(p & bitMask) { + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop;"); + *clr = pinMask; + } else { + *clr = pinMask; + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop;"); + } + if((bitMask >>= 1) != 0) { + asm("nop; nop; nop; nop; nop; nop; nop; nop; nop;"); + } else { + if(ptr >= end) break; + p = *ptr++; + bitMask = 0x80; + } + } + } else { // 400 KHz bitstream + for(;;) { + *set = pinMask; + // 11 cycles high regardless + asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); + if(p & bitMask) { + // 27 cycles high + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop;"); + *clr = pinMask; + } else { + *clr = pinMask; + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop;"); + } + asm("nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;" + "nop; nop; nop; nop; nop; nop; nop; nop;"); + if(bitMask >>= 1) { + asm("nop; nop; nop; nop; nop; nop; nop;"); + } else { + if(ptr >= end) break; + p = *ptr++; + bitMask = 0x80; + } + } + } + + // Turn on interrupts after timing-sensitive code. + mp_hal_enable_all_interrupts(); + + // 50us delay to let pixels latch to the data that was just sent. + // This could be optimized to only occur before pixel writes when necessary, + // like in the Arduino library. + delay_us(50); +} diff --git a/atmel-samd/common-hal/time/__init__.c b/atmel-samd/common-hal/time/__init__.c new file mode 100644 index 0000000000..0d60adef20 --- /dev/null +++ b/atmel-samd/common-hal/time/__init__.c @@ -0,0 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 "py/mphal.h" + +#include "shared-bindings/time/__init__.h" + +#include "tick.h" + +inline uint64_t common_hal_time_monotonic() { + return ticks_ms; +} + +void common_hal_time_delay_ms(uint32_t delay) { + mp_hal_delay_ms(delay); +} diff --git a/atmel-samd/internal_flash.c b/atmel-samd/internal_flash.c index 9bf4682eb4..642f0222ab 100644 --- a/atmel-samd/internal_flash.c +++ b/atmel-samd/internal_flash.c @@ -37,7 +37,7 @@ #include "asf/sam0/drivers/nvm/nvm.h" #include "asf/sam0/drivers/port/port.h" -#include "samdneopixel.h" +#include "neopixel_status.h" #define TOTAL_INTERNAL_FLASH_SIZE 0x010000 @@ -114,7 +114,7 @@ static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_blo buf[15] = num_blocks >> 24; } -static uint32_t convert_block_to_flash_addr(uint32_t block) { +static int32_t convert_block_to_flash_addr(uint32_t block) { if (INTERNAL_FLASH_PART1_START_BLOCK <= block && block < INTERNAL_FLASH_PART1_START_BLOCK + INTERNAL_FLASH_PART1_NUM_BLOCKS) { // a block in partition 1 block -= INTERNAL_FLASH_PART1_START_BLOCK; @@ -145,7 +145,7 @@ bool internal_flash_read_block(uint8_t *dest, uint32_t block) { } else { // non-MBR block, get data from flash memory - uint32_t src = convert_block_to_flash_addr(block); + int32_t src = convert_block_to_flash_addr(block); if (src == -1) { // bad block number return false; @@ -178,7 +178,7 @@ bool internal_flash_write_block(const uint8_t *src, uint32_t block) { temp_status_color(0x8f, 0x00, 0x00); #endif // non-MBR block, copy to cache - volatile uint32_t dest = convert_block_to_flash_addr(block); + int32_t dest = convert_block_to_flash_addr(block); if (dest == -1) { // bad block number return false; @@ -242,6 +242,8 @@ mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, ui return 0; // success } +void mark_flash_cache_for_gc(void) {} + /******************************************************************************/ // MicroPython bindings // diff --git a/atmel-samd/internal_flash.h b/atmel-samd/internal_flash.h index d59f7b38a4..ef0c8be1f4 100644 --- a/atmel-samd/internal_flash.h +++ b/atmel-samd/internal_flash.h @@ -47,6 +47,8 @@ bool internal_flash_write_block(const uint8_t *src, uint32_t block); mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); +void mark_flash_cache_for_gc(void); + extern const struct _mp_obj_type_t internal_flash_type; struct _fs_user_mount_t; diff --git a/atmel-samd/main.c b/atmel-samd/main.c index 1fbe7b298e..ac27e274b4 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -1,5 +1,4 @@ #include -#include #include #include "py/nlr.h" @@ -24,9 +23,9 @@ #include "autoreset.h" #include "mpconfigboard.h" -#include "modmachine_pin.h" -#include "samdneopixel.h" +#include "neopixel_status.h" #include "tick.h" +#include FLASH_INCLUDE fs_user_mount_t fs_user_mount_flash; @@ -82,7 +81,7 @@ extern void flash_init_vfs(fs_user_mount_t *vfs); // we don't make this function static because it needs a lot of stack and we // want it to be executed without using stack within main() function -void init_flash_fs() { +void init_flash_fs(void) { // init the vfs object fs_user_mount_t *vfs = &fs_user_mount_flash; vfs->str = "/flash"; @@ -148,9 +147,7 @@ void init_flash_fs() { } else { // doesn't exist, create fresh file - FIL fp; f_open(&fp, "/flash/boot.py", FA_WRITE | FA_CREATE_ALWAYS); - UINT n; f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes f_close(&fp); @@ -174,7 +171,7 @@ void init_flash_fs() { static char *stack_top; static char heap[16384]; -void reset_mp() { +void reset_mp(void) { new_status_color(0x8f, 0x00, 0x8f); autoreset_stop(); autoreset_enable(); @@ -196,11 +193,9 @@ void reset_mp() { mp_obj_list_init(mp_sys_argv, 0); MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt); - - pin_init0(); } -void reset_samd21() { +void reset_samd21(void) { // Reset all SERCOMs except the one being used by the SPI flash. Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS; for (int i = 0; i < SERCOM_INST_NUM; i++) { @@ -215,7 +210,7 @@ void reset_samd21() { // TODO(tannewt): Reset all of the pins too. } -void start_mp() { +void start_mp(void) { #ifdef AUTORESET_DELAY_MS mp_hal_stdout_tx_str("\r\n"); mp_hal_stdout_tx_str("Auto-soft reset is on. Simply save files over USB to run them.\r\n"); @@ -234,109 +229,6 @@ void start_mp() { pyexec_file("main.py"); } -int main(int argc, char **argv) { - // initialise the cpu and peripherals - #if MICROPY_MIN_USE_SAMD21_MCU - void samd21_init(void); - samd21_init(); - #endif - - - int stack_dummy; - // Store the location of stack_dummy as an approximation for the top of the - // stack so the GC can account for objects that may be referenced by the - // stack between here and where gc_collect is called. - stack_top = (char*)&stack_dummy; - reset_mp(); - - // Initialise the local flash filesystem after the gc in case we need to - // grab memory from it. Create it if needed, mount in on /flash, and set it - // as current dir. - init_flash_fs(); - - // Start USB after getting everything going. - #ifdef USB_REPL - udc_start(); - #endif - - // Run boot and main. - start_mp(); - - // Main script is finished, so now go into REPL mode. - // The REPL mode can change, or it can request a soft reset. - int exit_code = 0; - for (;;) { - new_status_color(0x3f, 0x3f, 0x3f); - if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { - exit_code = pyexec_raw_repl(); - } else { - exit_code = pyexec_friendly_repl(); - } - if (exit_code == PYEXEC_FORCED_EXIT) { - mp_hal_stdout_tx_str("soft reboot\r\n"); - reset_samd21(); - reset_mp(); - start_mp(); - } else if (exit_code != 0) { - break; - } - } - mp_deinit(); - return 0; -} - -void gc_collect(void) { - // WARNING: This gc_collect implementation doesn't try to get root - // pointers from CPU registers, and thus may function incorrectly. - void *dummy; - gc_collect_start(); - // This naively collects all object references from an approximate stack - // range. - gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); - gc_collect_end(); - gc_dump_info(); -} - -mp_lexer_t *fat_vfs_lexer_new_from_file(const char *filename); -mp_lexer_t *mp_lexer_new_from_file(const char *filename) { - #if MICROPY_VFS_FAT - return fat_vfs_lexer_new_from_file(filename); - #else - (void)filename; - return NULL; - #endif -} - -mp_import_stat_t fat_vfs_import_stat(const char *path); -mp_import_stat_t mp_import_stat(const char *path) { - #if MICROPY_VFS_FAT - return fat_vfs_import_stat(path); - #else - (void)path; - return MP_IMPORT_STAT_NO_EXIST; - #endif -} - -void mp_keyboard_interrupt(void) { - MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(mp_kbd_exception); -} - -void nlr_jump_fail(void *val) { -} - -void NORETURN __fatal_error(const char *msg) { - while (1); -} - -#ifndef NDEBUG -void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { - printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); - __fatal_error("Assertion failed"); -} -#endif - -#if MICROPY_MIN_USE_SAMD21_MCU - #ifdef UART_REPL struct usart_module usart_instance; #endif @@ -399,15 +291,103 @@ void samd21_init(void) { // port_pin_set_config(MICROPY_HW_LED1, &pin_conf); // port_pin_set_output_level(MICROPY_HW_LED1, false); + neopixel_status_init(); +} - #ifdef MICROPY_HW_NEOPIXEL - struct port_config pin_conf; - port_get_config_defaults(&pin_conf); +int main(int argc, char **argv) { + // initialise the cpu and peripherals + samd21_init(); - pin_conf.direction = PORT_PIN_DIR_OUTPUT; - port_pin_set_config(MICROPY_HW_NEOPIXEL, &pin_conf); - port_pin_set_output_level(MICROPY_HW_NEOPIXEL, false); + int stack_dummy; + // Store the location of stack_dummy as an approximation for the top of the + // stack so the GC can account for objects that may be referenced by the + // stack between here and where gc_collect is called. + stack_top = (char*)&stack_dummy; + reset_mp(); + + // Initialise the local flash filesystem after the gc in case we need to + // grab memory from it. Create it if needed, mount in on /flash, and set it + // as current dir. + init_flash_fs(); + + // Start USB after getting everything going. + #ifdef USB_REPL + udc_start(); + #endif + + // Run boot and main. + start_mp(); + + // Main script is finished, so now go into REPL mode. + // The REPL mode can change, or it can request a soft reset. + int exit_code = 0; + for (;;) { + new_status_color(0x3f, 0x3f, 0x3f); + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + exit_code = pyexec_raw_repl(); + } else { + exit_code = pyexec_friendly_repl(); + } + if (exit_code == PYEXEC_FORCED_EXIT) { + mp_hal_stdout_tx_str("soft reboot\r\n"); + reset_samd21(); + reset_mp(); + start_mp(); + } else if (exit_code != 0) { + break; + } + } + mp_deinit(); + return 0; +} + +void gc_collect(void) { + // WARNING: This gc_collect implementation doesn't try to get root + // pointers from CPU registers, and thus may function incorrectly. + void *dummy; + gc_collect_start(); + // This naively collects all object references from an approximate stack + // range. + gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t)); + mark_flash_cache_for_gc(); + gc_collect_end(); + gc_dump_info(); +} + +mp_lexer_t *fat_vfs_lexer_new_from_file(const char *filename); +mp_lexer_t *mp_lexer_new_from_file(const char *filename) { + #if MICROPY_VFS_FAT + return fat_vfs_lexer_new_from_file(filename); + #else + (void)filename; + return NULL; #endif } +mp_import_stat_t fat_vfs_import_stat(const char *path); +mp_import_stat_t mp_import_stat(const char *path) { + #if MICROPY_VFS_FAT + return fat_vfs_import_stat(path); + #else + (void)path; + return MP_IMPORT_STAT_NO_EXIST; + #endif +} + +void mp_keyboard_interrupt(void) { + MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(mp_kbd_exception); +} + +void nlr_jump_fail(void *val) { +} + +void NORETURN __fatal_error(const char *msg) { + while (1); +} + +#ifndef NDEBUG +void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) { + printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line); + __fatal_error("Assertion failed"); +} #endif diff --git a/atmel-samd/modmachine_adc.c b/atmel-samd/modmachine_adc.c deleted file mode 100644 index ac5e6a6f64..0000000000 --- a/atmel-samd/modmachine_adc.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 -#include - -#include "py/nlr.h" -#include "py/runtime.h" -#include "py/binary.h" -#include "py/mphal.h" -#include "modmachine_adc.h" -#include "modmachine_pin.h" - -#include "asf/sam0/drivers/adc/adc.h" - -/// \moduleref machine -/// \class ADC - analog to digital conversion: read analog values on a pin -/// -/// Usage: -/// -/// adc = machine.ADC(pin) # create an analog object from a pin -/// val = adc.read() # read an analog value - -typedef struct { - mp_obj_base_t base; - pin_obj_t * pin; - struct adc_module adc_instance; -} adc_obj_t; - -/******************************************************************************/ -/* Micro Python bindings : adc object (single channel) */ - -STATIC void adc_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - adc_obj_t *self = self_in; - mp_print_str(print, "pin, PRINT_STR); -} - - -STATIC void adc_init_single(adc_obj_t *adc_obj) { - struct adc_config config_adc; - adc_get_config_defaults(&config_adc); - - config_adc.positive_input = adc_obj->pin->adc_input; - config_adc.resolution = ADC_RESOLUTION_CUSTOM; - config_adc.accumulate_samples = ADC_ACCUMULATE_SAMPLES_16; - config_adc.divide_result = ADC_DIVIDE_RESULT_16; - config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV128; - - adc_init(&adc_obj->adc_instance, ADC, &config_adc); -} - -/// \classmethod \constructor(pin) -/// Create an ADC object associated with the given pin. -/// This allows you to then read analog values on that pin. -STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { - // check number of arguments - mp_arg_check_num(n_args, n_kw, 1, 1, false); - - // 1st argument is the pin name - mp_obj_t pin_obj = args[0]; - - const pin_obj_t *pin = pin_find(pin_obj); - if (!pin->has_adc) { - // No ADC function on that pin - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %q does not have ADC capabilities", pin->name)); - } - - adc_obj_t *o = m_new_obj(adc_obj_t); - memset(o, 0, sizeof(*o)); - o->base.type = &adc_type; - o->pin = pin_obj; - adc_init_single(o); - - return o; -} - -/// \method read() -/// Read the value on the analog pin and return it. The returned value -/// will be between 0 and 4095. -// TODO(tannewt): Don't turn it all on just for one read. This simplifies -// handling of reading multiple inputs and surviving sleep though so for now its -// ok. -STATIC mp_obj_t mp_adc_read(mp_obj_t self_in) { - adc_obj_t *self = self_in; - - adc_enable(&self->adc_instance); - adc_start_conversion(&self->adc_instance); - - uint16_t data; - enum status_code status = adc_read(&self->adc_instance, &data); - while (status == STATUS_BUSY) { - status = adc_read(&self->adc_instance, &data); - } - if (status == STATUS_ERR_OVERFLOW) { - // TODO(tannewt): Throw an error. - } - - adc_disable(&self->adc_instance); - return mp_obj_new_int(data); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, mp_adc_read); - -STATIC const mp_map_elem_t adc_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&adc_read_obj}, -}; - -STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table); - -const mp_obj_type_t adc_type = { - { &mp_type_type }, - .name = MP_QSTR_ADC, - .print = adc_print, - .make_new = adc_make_new, - .locals_dict = (mp_obj_t)&adc_locals_dict, -}; diff --git a/atmel-samd/modmachine_dac.c b/atmel-samd/modmachine_dac.c deleted file mode 100644 index b69fd44dcd..0000000000 --- a/atmel-samd/modmachine_dac.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * 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 -#include -#include - -#include "py/runtime.h" -#include "modmachine_dac.h" - -#include "asf/sam0/drivers/dac/dac.h" - -/// \moduleref machine -/// \class DAC - digital to analog conversion -/// -/// The DAC is used to output analog values (a specific voltage) on pin PA02 -/// (Arduino Zero A0, Feather MO Bluefruit A0). -/// The voltage will be between 0 and 3.3V. -/// -/// *This module will undergo changes to the API.* -/// -/// Example usage: -/// -/// from machine import DAC -/// -/// dac = DAC() # create DAC 1 on pin PA02 -/// dac.write(512) # write a value to the DAC (makes PA02 1.65V) -/// dac.write_mv(1650) # Also results in PA02 being 1.65V - -/******************************************************************************/ -// Micro Python bindings - -typedef struct _dac_obj_t { - mp_obj_base_t base; - struct dac_module dac_instance; -} dac_obj_t; - -// create the dac object - -/// \classmethod \constructor() -/// Construct a new DAC object for pin PA02. -STATIC mp_obj_t dac_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); - - dac_obj_t *dac = m_new_obj(dac_obj_t); - dac->base.type = &dac_type; - - struct dac_config config_dac; - dac_get_config_defaults(&config_dac); - config_dac.reference = DAC_REFERENCE_AVCC; - enum status_code status = dac_init(&dac->dac_instance, DAC, &config_dac); - if (status != STATUS_OK) { - // Throw error. - return mp_const_none; - } - - struct dac_chan_config config_dac_chan; - dac_chan_get_config_defaults(&config_dac_chan); - dac_chan_set_config(&dac->dac_instance, DAC_CHANNEL_0, &config_dac_chan); - dac_chan_enable(&dac->dac_instance, DAC_CHANNEL_0); - - dac_enable(&dac->dac_instance); - - // return object - return dac; -} - -/// \method deinit() -/// Turn off the DAC, enable other use of pin. -STATIC mp_obj_t dac_del(mp_obj_t self_in) { - dac_obj_t *self = self_in; - - dac_disable(&self->dac_instance); - dac_chan_disable(&self->dac_instance, DAC_CHANNEL_0); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(dac_del_obj, dac_del); - -/// \method write(value) -/// Direct access to the DAC output (10 bit). -STATIC mp_obj_t dac_write(mp_obj_t self_in, mp_obj_t val) { - dac_obj_t *self = self_in; - - dac_chan_write(&self->dac_instance, DAC_CHANNEL_0, mp_obj_get_int(val)); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(dac_write_obj, dac_write); - -/// \method write_mv(value) -/// Direct access to the DAC output by specifying millivolts. -STATIC mp_obj_t dac_write_mv(mp_obj_t self_in, mp_obj_t val_mv) { - dac_obj_t *self = self_in; - // TODO(tannewt): Sanity check that the mv value is less than the reference - // voltage. - uint16_t val = ((uint32_t) mp_obj_get_int(val_mv)) * 1023 / 3300; - - dac_chan_write(&self->dac_instance, DAC_CHANNEL_0, val); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(dac_write_mv_obj, dac_write_mv); - -STATIC const mp_map_elem_t dac_locals_dict_table[] = { - // instance methods - { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&dac_del_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&dac_write_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_write_mv), (mp_obj_t)&dac_write_mv_obj }, -}; - -STATIC MP_DEFINE_CONST_DICT(dac_locals_dict, dac_locals_dict_table); - -const mp_obj_type_t dac_type = { - { &mp_type_type }, - .name = MP_QSTR_DAC, - .make_new = dac_make_new, - .locals_dict = (mp_obj_t)&dac_locals_dict, -}; diff --git a/atmel-samd/modmachine_pin.c b/atmel-samd/modmachine_pin.c deleted file mode 100644 index 14c809057e..0000000000 --- a/atmel-samd/modmachine_pin.c +++ /dev/null @@ -1,438 +0,0 @@ -/* - * 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 -#include -#include - -#include "py/nlr.h" -#include "py/runtime.h" -#include "py/mphal.h" -#include "modmachine_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/modmachine_pin.h b/atmel-samd/modmachine_pin.h deleted file mode 100644 index 71adf46a78..0000000000 --- a/atmel-samd/modmachine_pin.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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__ - -// Don't reorder these includes because they are dependencies of adc_feature.h. -// They should really be included by adc_feature.h. -#include "compiler.h" -#include "asf/sam0/drivers/system/clock/gclk.h" -#include "asf/sam0/utils/cmsis/samd21/include/component/adc.h" -#include "asf/sam0/drivers/adc/adc_sam_d_r/adc_feature.h" - -#include "machine_types.h" - -#define SERCOM(p_sercom, p_pad, p_pinmux) \ -{ \ - .sercom = p_sercom, \ - .pad = p_pad, \ - .pinmux = p_pinmux \ -} - -#define NO_SERCOM SERCOM(0, 0, 0) - -#define TIMER(p_tc, p_tcc, p_channel, p_wave_output, p_pin, p_mux) \ -{ \ - .tc = p_tc, \ - .tcc = p_tcc, \ - .channel = p_channel, \ - .wave_output = p_wave_output, \ - .pin = p_pin, \ - .mux = p_mux \ -} - -#define NO_TIMER TIMER(0, 0, 0, 0, 0, 0) - -// This macro is used to simplify pin definition in boards//pins.c -#define PIN(p_name, p_has_adc, p_adc_input, p_primary_timer, \ - p_secondary_timer, p_primary_sercom, p_secondary_sercom) \ -const pin_obj_t pin_## p_name = { \ - { &pin_type }, \ - .name = MP_QSTR_ ## p_name, \ - .pin = (PIN_## p_name), \ - .has_adc = p_has_adc, \ - .adc_input = p_adc_input, \ - .primary_timer = p_primary_timer, \ - .secondary_timer = p_secondary_timer, \ - .sercom = {p_primary_sercom, p_secondary_sercom}, \ -} - -#define NO_ADC_INPUT (0) - -#include "mpconfigport.h" - -#include "py/obj.h" - -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_KW(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/modmachine_pwm.c b/atmel-samd/modmachine_pwm.c deleted file mode 100644 index 214210f504..0000000000 --- a/atmel-samd/modmachine_pwm.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * This file is part of the Micro Python project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 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 -#include - -#include "py/runtime.h" -#include "modmachine_pin.h" -#include "modmachine_pwm.h" - -#include "asf/sam0/drivers/tc/tc.h" -#include "asf/sam0/drivers/tcc/tcc.h" - -typedef struct _pwm_obj_t { - mp_obj_base_t base; - const pin_obj_t *pin; - bool using_primary_timer; - struct tc_module tc_instance; - struct tcc_module tcc_instance; -} pwm_obj_t; - -/******************************************************************************/ -// MicroPython bindings for PWM - -STATIC void pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "PWM(%s", self->pin->name); - mp_printf(print, ", freq=%u, duty=%u", 0, 0); - mp_printf(print, ")"); -} -/// \classmethod \constructor(pin) -/// Create a PWM object associated with the given pin. This allows you to write PWM -/// signals out on the given pin. Frequency is currently fixed at ~735Hz like Arduino. -STATIC mp_obj_t pwm_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); - mp_obj_t pin_obj = args[0]; - const pin_obj_t *pin = pin_find(pin_obj); - - // create PWM object from the given pin - pwm_obj_t *self = m_new_obj(pwm_obj_t); - self->base.type = &pwm_type; - self->pin = pin; - self->using_primary_timer = true; - - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); - enum { ARG_duty }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_duty, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, - }; - mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, args + 1, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args); - - if (pin->primary_timer.tc == 0 && pin->primary_timer.tcc == 0 && - pin->secondary_timer.tc == 0 && pin->secondary_timer.tcc == 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - "PWM not supported on pin %q", self->pin->name)); - } - - if (parsed_args[ARG_duty].u_int < 0 || parsed_args[ARG_duty].u_int > 255) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - "PWM duty must be between 0 and 255 (8 bit resolution), not %d", - parsed_args[ARG_duty].u_int)); - } - uint8_t duty = parsed_args[ARG_duty].u_int; - - // TODO(tannewt): Support output on multiple timer channels at once. - const pin_timer_t* t = &pin->primary_timer; - if (t->tcc != 0) { - struct tcc_config config_tcc; - tcc_get_config_defaults(&config_tcc, t->tcc); - - config_tcc.counter.clock_prescaler = TCC_CLOCK_PRESCALER_DIV256; - config_tcc.counter.period = 0xFF; - config_tcc.compare.wave_generation = TCC_WAVE_GENERATION_SINGLE_SLOPE_PWM; - config_tcc.compare.match[t->channel] = duty; - - config_tcc.pins.enable_wave_out_pin[t->wave_output] = true; - config_tcc.pins.wave_out_pin[t->wave_output] = t->pin; - config_tcc.pins.wave_out_pin_mux[t->wave_output] = t->mux; - - tcc_init(&self->tcc_instance, t->tcc, &config_tcc); - - tcc_enable(&self->tcc_instance); - } else { - struct tc_config config_tc; - tc_get_config_defaults(&config_tc); - - config_tc.counter_size = TC_COUNTER_SIZE_8BIT; - config_tc.wave_generation = TC_WAVE_GENERATION_NORMAL_PWM; - config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV256; - config_tc.counter_8_bit.period = 0xff; - config_tc.counter_8_bit.compare_capture_channel[t->channel] = duty; - - config_tc.pwm_channel[t->wave_output].enabled = true; - config_tc.pwm_channel[t->wave_output].pin_out = t->pin; - config_tc.pwm_channel[t->wave_output].pin_mux = t->mux; - - tc_init(&self->tc_instance, t->tc, &config_tc); - - tc_enable(&self->tc_instance); - } - - return MP_OBJ_FROM_PTR(self); -} - -STATIC mp_obj_t pwm_del(mp_obj_t self_in) { - pwm_obj_t *self = MP_OBJ_TO_PTR(self_in); - const pin_timer_t* t = &self->pin->primary_timer; - if (!self->using_primary_timer) { - t = &self->pin->secondary_timer; - } - if (t->tcc != 0) { - tcc_disable(&self->tcc_instance); - } else { - tc_disable(&self->tc_instance); - } - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(pwm_del_obj, pwm_del); - -// 8 bit resolution -STATIC mp_obj_t pwm_duty(size_t n_args, const mp_obj_t *args) { - pwm_obj_t *self = MP_OBJ_TO_PTR(args[0]); - - const pin_timer_t* t = &self->pin->primary_timer; - if (!self->using_primary_timer) { - t = &self->pin->secondary_timer; - } - - if (n_args == 1) { - uint8_t duty; - if (t->tcc != 0) { - duty = tcc_get_capture_value(&self->tcc_instance, t->channel); - } else { - duty = tc_get_capture_value(&self->tc_instance, t->channel); - } - return MP_OBJ_NEW_SMALL_INT(duty); - } else { - mp_int_t duty = mp_obj_get_int(args[1]); - if (duty < 0 || duty > 255) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - "PWM duty must be between 0 and 255 (8 bit resolution), not %d", - duty)); - } - if (t->tcc != 0) { - tcc_set_compare_value(&self->tcc_instance, t->channel, duty); - } else { - tc_set_compare_value(&self->tc_instance, t->channel, duty); - } - return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pwm_duty_obj, 1, 2, pwm_duty); - -STATIC const mp_rom_map_elem_t pwm_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&pwm_del_obj) }, - { MP_ROM_QSTR(MP_QSTR_duty), MP_ROM_PTR(&pwm_duty_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(pwm_locals_dict, pwm_locals_dict_table); - -const mp_obj_type_t pwm_type = { - { &mp_type_type }, - .name = MP_QSTR_PWM, - .print = pwm_print, - .make_new = pwm_make_new, - .locals_dict = (mp_obj_dict_t*)&pwm_locals_dict, -}; diff --git a/atmel-samd/modneopixel_write.c b/atmel-samd/modneopixel_write.c deleted file mode 100644 index 024e4b1c50..0000000000 --- a/atmel-samd/modneopixel_write.c +++ /dev/null @@ -1,34 +0,0 @@ -#include - -#include "py/obj.h" -#include "py/mphal.h" -#include "py/runtime.h" - -#include "modmachine_pin.h" -#include "samdneopixel.h" - -extern const mp_obj_type_t pin_type; - -STATIC mp_obj_t neopixel_write_neopixel_write_(mp_obj_t pin_obj, mp_obj_t buf, mp_obj_t is800k) { - // Convert parameters into expected types. - const pin_obj_t *pin = pin_find(pin_obj); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - // Call platform's neopixel write function with provided buffer and options. - samd_neopixel_write(pin->pin, (uint8_t*)bufinfo.buf, bufinfo.len, - mp_obj_is_true(is800k)); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(neopixel_write_neopixel_write_obj, neopixel_write_neopixel_write_); - -STATIC const mp_rom_map_elem_t neopixel_write_module_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&neopixel_write_neopixel_write_obj }, -}; - -STATIC MP_DEFINE_CONST_DICT(neopixel_write_module_globals, neopixel_write_module_globals_table); - -const mp_obj_module_t neopixel_write_module = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&neopixel_write_module_globals, -}; diff --git a/atmel-samd/moduos.c b/atmel-samd/moduos.c index d8cb9d8e4b..33bf7acaf9 100644 --- a/atmel-samd/moduos.c +++ b/atmel-samd/moduos.c @@ -329,22 +329,6 @@ STATIC mp_obj_t os_sync(void) { } MP_DEFINE_CONST_FUN_OBJ_0(mod_os_sync_obj, os_sync); -#if MICROPY_HW_ENABLE_RNG -/// \function urandom(n) -/// Return a bytes object with n random bytes, generated by the hardware -/// random number generator. -STATIC mp_obj_t os_urandom(mp_obj_t num) { - mp_int_t n = mp_obj_get_int(num); - vstr_t vstr; - vstr_init_len(&vstr, n); - for (int i = 0; i < n; i++) { - vstr.buf[i] = rng_get(); - } - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom); -#endif - STATIC const mp_map_elem_t os_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uos) }, @@ -366,10 +350,6 @@ STATIC const mp_map_elem_t os_module_globals_table[] = { /// \constant sep - separation character used in paths { MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) }, -#if MICROPY_HW_ENABLE_RNG - { MP_OBJ_NEW_QSTR(MP_QSTR_urandom), (mp_obj_t)&os_urandom_obj }, -#endif - // these are MicroPython extensions { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&fsuser_mount_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_umount), (mp_obj_t)&fsuser_umount_obj }, diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h index ab78cc8dc3..225992c519 100644 --- a/atmel-samd/mpconfigport.h +++ b/atmel-samd/mpconfigport.h @@ -48,6 +48,7 @@ #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ATTRTUPLE (1) #define MICROPY_PY_COLLECTIONS (1) +#define MICROPY_PY_DESCRIPTORS (1) #define MICROPY_PY_FRAMEBUF (1) #define MICROPY_PY_MATH (1) #define MICROPY_PY_CMATH (1) @@ -111,15 +112,19 @@ typedef long mp_off_t; { MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj }, // extra built in modules to add to the list of known ones -extern const struct _mp_obj_module_t machine_module; +extern const struct _mp_obj_module_t microcontroller_module; +extern const struct _mp_obj_module_t nativeio_module; +extern const struct _mp_obj_module_t board_module; extern const struct _mp_obj_module_t uos_module; -extern const struct _mp_obj_module_t utime_module; +extern const struct _mp_obj_module_t time_module; extern const struct _mp_obj_module_t neopixel_write_module; #define MICROPY_PORT_BUILTIN_MODULES \ - { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)µcontroller_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_nativeio), (mp_obj_t)&nativeio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_utime), (mp_obj_t)&utime_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module } \ // board specific definitions @@ -147,7 +152,5 @@ extern const struct _mp_obj_module_t neopixel_write_module; const char *readline_hist[8]; \ vstr_t *repl_line; \ mp_obj_t mp_kbd_exception; \ - mp_obj_t pin_class_mapper; \ - mp_obj_t pin_class_map_dict; \ #endif // __INCLUDED_MPCONFIGPORT_H diff --git a/atmel-samd/mphalport.c b/atmel-samd/mphalport.c index 01a9647537..b7887925a4 100644 --- a/atmel-samd/mphalport.c +++ b/atmel-samd/mphalport.c @@ -11,6 +11,7 @@ #include "py/mphal.h" #include "py/mpstate.h" #include "py/smallint.h" +#include "shared-bindings/time/__init__.h" #include "mpconfigboard.h" #include "mphalport.h" @@ -126,7 +127,7 @@ void usb_rx_notify(void) } } -int receive_usb() { +int receive_usb(void) { if (usb_rx_count == 0) { return 0; } @@ -197,8 +198,8 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) { // string. If there isn't we risk getting caught in a loop within the usb // code as it tries to send all the characters it can't buffer. uint32_t start = 0; - uint32_t start_tick = mp_hal_ticks_ms(); - uint32_t duration = 0; + uint64_t start_tick = common_hal_time_monotonic(); + uint64_t duration = 0; if (mp_cdc_enabled) { while (start < len && duration < 10) { uint8_t buffer_space = udi_cdc_get_free_tx_buffer(); @@ -213,17 +214,17 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) { if (mp_msc_enabled) { udi_msc_process_trans(); } - duration = (mp_hal_ticks_ms() - start_tick) & MP_SMALL_INT_POSITIVE_MASK; + duration = (common_hal_time_monotonic() - start_tick); } } #endif } +extern int interrupt_char; void mp_hal_set_interrupt_char(int c) { if (c != -1) { mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_kbd_exception)); } - extern int interrupt_char; interrupt_char = c; } @@ -232,15 +233,15 @@ void mp_hal_delay_ms(mp_uint_t delay) { // storage transactions in the meantime. // TODO(tannewt): Break out of this delay on KeyboardInterrupt too. if (mp_msc_enabled) { - uint32_t start_tick = mp_hal_ticks_ms(); - uint32_t duration = 0; + uint64_t start_tick = common_hal_time_monotonic(); + uint64_t duration = 0; while (duration < delay) { udi_msc_process_trans(); // Check to see if we've been CTRL-Ced by autoreset or the user. if(MP_STATE_VM(mp_pending_exception) == MP_STATE_PORT(mp_kbd_exception)) { break; } - duration = (mp_hal_ticks_ms() - start_tick) & MP_SMALL_INT_POSITIVE_MASK; + duration = (common_hal_time_monotonic() - start_tick); } } else { delay_ms(delay); diff --git a/atmel-samd/mphalport.h b/atmel-samd/mphalport.h index 858d628134..6df09f9c71 100644 --- a/atmel-samd/mphalport.h +++ b/atmel-samd/mphalport.h @@ -32,7 +32,7 @@ #define USB_RX_BUF_SIZE 128 // Global millisecond tick count (driven by SysTick interrupt). -extern volatile uint32_t ticks_ms; +extern volatile uint64_t ticks_ms; static inline mp_uint_t mp_hal_ticks_ms(void) { return ticks_ms; diff --git a/atmel-samd/neopixel_status.c b/atmel-samd/neopixel_status.c new file mode 100644 index 0000000000..86dd2cb282 --- /dev/null +++ b/atmel-samd/neopixel_status.c @@ -0,0 +1,43 @@ +#include "asf/common2/services/delay/delay.h" +#include "asf/sam0/drivers/port/port.h" + +#include "mphalport.h" + +#include "shared-bindings/nativeio/DigitalInOut.h" +#include "shared-bindings/neopixel_write/__init__.h" +#include "neopixel_status.h" +#include "samd21_pins.h" + +#ifdef MICROPY_HW_NEOPIXEL +static uint8_t status_neopixel_color[3]; +static nativeio_digitalinout_obj_t status_neopixel; +#endif + +void neopixel_status_init() { + #ifdef MICROPY_HW_NEOPIXEL + common_hal_nativeio_digitalinout_construct(&status_neopixel, MICROPY_HW_NEOPIXEL); + common_hal_nativeio_digitalinout_switch_to_output(&status_neopixel, false, DRIVE_MODE_PUSH_PULL); + #endif +} + +void new_status_color(uint8_t r, uint8_t g, uint8_t b) { + #ifdef MICROPY_HW_NEOPIXEL + status_neopixel_color[0] = g; + status_neopixel_color[1] = r; + status_neopixel_color[2] = b; + common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3, true); + #endif +} + +void temp_status_color(uint8_t r, uint8_t g, uint8_t b) { + #ifdef MICROPY_HW_NEOPIXEL + uint8_t colors[3] = {g, r, b}; + common_hal_neopixel_write(&status_neopixel, colors, 3, true); + #endif +} + +void clear_temp_status() { + #ifdef MICROPY_HW_NEOPIXEL + common_hal_neopixel_write(&status_neopixel, status_neopixel_color, 3, true); + #endif +} diff --git a/atmel-samd/neopixel_status.h b/atmel-samd/neopixel_status.h new file mode 100644 index 0000000000..a09fd7b918 --- /dev/null +++ b/atmel-samd/neopixel_status.h @@ -0,0 +1,12 @@ +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_NEOPIXEL_STATUS_H +#define __MICROPY_INCLUDED_ATMEL_SAMD_NEOPIXEL_STATUS_H + +#include +#include + +extern void neopixel_status_init(void); +extern void new_status_color(uint8_t r, uint8_t g, uint8_t b); +extern void temp_status_color(uint8_t r, uint8_t g, uint8_t b); +extern void clear_temp_status(void); + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_NEOPIXEL_STATUS_H diff --git a/atmel-samd/pin_defs_samd.c b/atmel-samd/pin_defs_samd.c deleted file mode 100644 index 2ffce52346..0000000000 --- a/atmel-samd/pin_defs_samd.c +++ /dev/null @@ -1,57 +0,0 @@ -#include -#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/boards/samd21_pins.c b/atmel-samd/samd21_pins.c similarity index 73% rename from atmel-samd/boards/samd21_pins.c rename to atmel-samd/samd21_pins.c index c86d7df1fc..7298bee853 100644 --- a/atmel-samd/boards/samd21_pins.c +++ b/atmel-samd/samd21_pins.c @@ -1,4 +1,43 @@ -#include "boards/samd21_pins.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "samd21_pins.h" + +#define SERCOM(p_sercom, p_pad, p_pinmux) \ +{ \ + .sercom = p_sercom, \ + .pad = p_pad, \ + .pinmux = p_pinmux \ +} + +#define NO_SERCOM SERCOM(0, 0, 0) + +#define TIMER(p_tc, p_tcc, p_channel, p_wave_output, p_pin, p_mux) \ +{ \ + .tc = p_tc, \ + .tcc = p_tcc, \ + .channel = p_channel, \ + .wave_output = p_wave_output, \ + .pin = p_pin, \ + .mux = p_mux \ +} + +#define NO_TIMER TIMER(0, 0, 0, 0, 0, 0) + +// This macro is used to simplify pin definition in boards//pins.c +#define PIN(p_name, p_has_adc, p_adc_input, p_primary_timer, \ + p_secondary_timer, p_primary_sercom, p_secondary_sercom) \ +const mcu_pin_obj_t pin_## p_name = { \ + { &mcu_pin_type }, \ + .name = MP_QSTR_ ## p_name, \ + .pin = (PIN_## p_name), \ + .has_adc = p_has_adc, \ + .adc_input = p_adc_input, \ + .primary_timer = p_primary_timer, \ + .secondary_timer = p_secondary_timer, \ + .sercom = {p_primary_sercom, p_secondary_sercom}, \ +} + +#define NO_ADC_INPUT (0) // Pins in datasheet order. #ifdef PIN_PA00 @@ -407,166 +446,3 @@ PIN(PB03, true, ADC_POSITIVE_INPUT_PIN11, NO_SERCOM, SERCOM(SERCOM5, 1, PINMUX_PB03D_SERCOM5_PAD1)); #endif - -STATIC const mp_map_elem_t pin_cpu_pins_locals_dict_table[] = { -// Pins in datasheet order. -#ifdef PIN_PA00 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA00), (mp_obj_t)&pin_PA00 }, -#endif -#ifdef PIN_PA01 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA01), (mp_obj_t)&pin_PA01 }, -#endif -#ifdef PIN_PA02 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA02), (mp_obj_t)&pin_PA02 }, -#endif -#ifdef PIN_PA03 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA03), (mp_obj_t)&pin_PA03 }, -#endif -#ifdef PIN_PB04 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB04), (mp_obj_t)&pin_PB04 }, -#endif -#ifdef PIN_PB05 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB05), (mp_obj_t)&pin_PB05 }, -#endif -#ifdef PIN_PB06 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB06), (mp_obj_t)&pin_PB06 }, -#endif -#ifdef PIN_PB07 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB07), (mp_obj_t)&pin_PB07 }, -#endif -#ifdef PIN_PB08 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB08), (mp_obj_t)&pin_PB08 }, -#endif -#ifdef PIN_PB09 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB09), (mp_obj_t)&pin_PB09 }, -#endif -#ifdef PIN_PA04 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA04), (mp_obj_t)&pin_PA04 }, -#endif -#ifdef PIN_PA05 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA05), (mp_obj_t)&pin_PA05 }, -#endif -#ifdef PIN_PA06 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA06), (mp_obj_t)&pin_PA06 }, -#endif -#ifdef PIN_PA07 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA07), (mp_obj_t)&pin_PA07 }, -#endif -#ifdef PIN_PA08 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA08), (mp_obj_t)&pin_PA08 }, -#endif -#ifdef PIN_PA09 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA09), (mp_obj_t)&pin_PA09 }, -#endif -#ifdef PIN_PA10 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA10), (mp_obj_t)&pin_PA10 }, -#endif -#ifdef PIN_PA11 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA11), (mp_obj_t)&pin_PA11 }, -#endif -#ifdef PIN_PB10 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB10), (mp_obj_t)&pin_PB10 }, -#endif -#ifdef PIN_PB11 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB11), (mp_obj_t)&pin_PB11 }, -#endif -#ifdef PIN_PB12 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB12), (mp_obj_t)&pin_PB12 }, -#endif -#ifdef PIN_PB13 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB13), (mp_obj_t)&pin_PB13 }, -#endif -#ifdef PIN_PB14 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB14), (mp_obj_t)&pin_PB14 }, -#endif - -// Second page. -#ifdef PIN_PB15 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB15), (mp_obj_t)&pin_PB15 }, -#endif -#ifdef PIN_PA12 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA12), (mp_obj_t)&pin_PA12 }, -#endif -#ifdef PIN_PA13 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA13), (mp_obj_t)&pin_PA13 }, -#endif -#ifdef PIN_PA14 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA14), (mp_obj_t)&pin_PA14 }, -#endif -#ifdef PIN_PA15 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA15), (mp_obj_t)&pin_PA15 }, -#endif -#ifdef PIN_PA16 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA16), (mp_obj_t)&pin_PA16 }, -#endif -#ifdef PIN_PA17 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA17), (mp_obj_t)&pin_PA17 }, -#endif -#ifdef PIN_PA18 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA18), (mp_obj_t)&pin_PA18 }, -#endif -#ifdef PIN_PA19 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA19), (mp_obj_t)&pin_PA19 }, -#endif -#ifdef PIN_PB16 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB16), (mp_obj_t)&pin_PB16 }, -#endif -#ifdef PIN_PB17 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB17), (mp_obj_t)&pin_PB17 }, -#endif -#ifdef PIN_PA20 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA20), (mp_obj_t)&pin_PA20 }, -#endif -#ifdef PIN_PA21 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA21), (mp_obj_t)&pin_PA21 }, -#endif -#ifdef PIN_PA22 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA22), (mp_obj_t)&pin_PA22 }, -#endif -#ifdef PIN_PA23 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA23), (mp_obj_t)&pin_PA23 }, -#endif -#ifdef PIN_PA24 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA24), (mp_obj_t)&pin_PA24 }, -#endif -#ifdef PIN_PA25 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA25), (mp_obj_t)&pin_PA25 }, -#endif -#ifdef PIN_PB22 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB22), (mp_obj_t)&pin_PB22 }, -#endif -#ifdef PIN_PB23 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB23), (mp_obj_t)&pin_PB23 }, -#endif -#ifdef PIN_PA27 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA27), (mp_obj_t)&pin_PA27 }, -#endif -#ifdef PIN_PA28 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA28), (mp_obj_t)&pin_PA28 }, -#endif -#ifdef PIN_PA30 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA30), (mp_obj_t)&pin_PA30 }, -#endif -#ifdef PIN_PA31 - { MP_OBJ_NEW_QSTR(MP_QSTR_PA31), (mp_obj_t)&pin_PA31 }, -#endif -#ifdef PIN_PB30 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB30), (mp_obj_t)&pin_PB30 }, -#endif -#ifdef PIN_PB31 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB31), (mp_obj_t)&pin_PB31 }, -#endif -#ifdef PIN_PB00 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB00), (mp_obj_t)&pin_PB00 }, -#endif -#ifdef PIN_PB01 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB01), (mp_obj_t)&pin_PB01 }, -#endif -#ifdef PIN_PB02 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB02), (mp_obj_t)&pin_PB02 }, -#endif -#ifdef PIN_PB03 - { MP_OBJ_NEW_QSTR(MP_QSTR_PB03), (mp_obj_t)&pin_PB03 } -#endif -}; -MP_DEFINE_CONST_DICT(pin_cpu_pins_locals_dict, pin_cpu_pins_locals_dict_table); diff --git a/atmel-samd/samd21_pins.h b/atmel-samd/samd21_pins.h new file mode 100644 index 0000000000..e2fd57a73a --- /dev/null +++ b/atmel-samd/samd21_pins.h @@ -0,0 +1,166 @@ +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H__ + +#include "common-hal/microcontroller/types.h" + +// Pins in datasheet order. +#ifdef PIN_PA00 +extern const mcu_pin_obj_t pin_PA00; +#endif +#ifdef PIN_PA01 +extern const mcu_pin_obj_t pin_PA01; +#endif +#ifdef PIN_PA02 +extern const mcu_pin_obj_t pin_PA02; +#endif +#ifdef PIN_PA03 +extern const mcu_pin_obj_t pin_PA03; +#endif +#ifdef PIN_PB04 +extern const mcu_pin_obj_t pin_PB04; +#endif +#ifdef PIN_PB05 +extern const mcu_pin_obj_t pin_PB05; +#endif +#ifdef PIN_PB06 +extern const mcu_pin_obj_t pin_PB06; +#endif +#ifdef PIN_PB07 +extern const mcu_pin_obj_t pin_PB07; +#endif +#ifdef PIN_PB08 +extern const mcu_pin_obj_t pin_PB08; +#endif +#ifdef PIN_PB09 +extern const mcu_pin_obj_t pin_PB09; +#endif +#ifdef PIN_PA04 +extern const mcu_pin_obj_t pin_PA04; +#endif +#ifdef PIN_PA05 +extern const mcu_pin_obj_t pin_PA05; +#endif +#ifdef PIN_PA06 +extern const mcu_pin_obj_t pin_PA06; +#endif +#ifdef PIN_PA07 +extern const mcu_pin_obj_t pin_PA07; +#endif +#ifdef PIN_PA08 +extern const mcu_pin_obj_t pin_PA08; +#endif +#ifdef PIN_PA09 +extern const mcu_pin_obj_t pin_PA09; +#endif +#ifdef PIN_PA10 +extern const mcu_pin_obj_t pin_PA10; +#endif +#ifdef PIN_PA11 +extern const mcu_pin_obj_t pin_PA11; +#endif +#ifdef PIN_PB10 +extern const mcu_pin_obj_t pin_PB10; +#endif +#ifdef PIN_PB11 +extern const mcu_pin_obj_t pin_PB11; +#endif +#ifdef PIN_PB12 +extern const mcu_pin_obj_t pin_PB12; +#endif +#ifdef PIN_PB13 +extern const mcu_pin_obj_t pin_PB13; +#endif +#ifdef PIN_PB14 +extern const mcu_pin_obj_t pin_PB14; +#endif + +// Second page. +#ifdef PIN_PB15 +extern const mcu_pin_obj_t pin_PB15; +#endif +#ifdef PIN_PA12 +extern const mcu_pin_obj_t pin_PA12; +#endif +#ifdef PIN_PA13 +extern const mcu_pin_obj_t pin_PA13; +#endif +#ifdef PIN_PA14 +extern const mcu_pin_obj_t pin_PA14; +#endif +#ifdef PIN_PA15 +extern const mcu_pin_obj_t pin_PA15; +#endif +#ifdef PIN_PA16 +extern const mcu_pin_obj_t pin_PA16; +#endif +#ifdef PIN_PA17 +extern const mcu_pin_obj_t pin_PA17; +#endif +#ifdef PIN_PA18 +extern const mcu_pin_obj_t pin_PA18; +#endif +#ifdef PIN_PA19 +extern const mcu_pin_obj_t pin_PA19; +#endif +#ifdef PIN_PB16 +extern const mcu_pin_obj_t pin_PB16; +#endif +#ifdef PIN_PB17 +extern const mcu_pin_obj_t pin_PB17; +#endif +#ifdef PIN_PA20 +extern const mcu_pin_obj_t pin_PA20; +#endif +#ifdef PIN_PA21 +extern const mcu_pin_obj_t pin_PA21; +#endif +#ifdef PIN_PA22 +extern const mcu_pin_obj_t pin_PA22; +#endif +#ifdef PIN_PA23 +extern const mcu_pin_obj_t pin_PA23; +#endif +#ifdef PIN_PA24 +extern const mcu_pin_obj_t pin_PA24; +#endif +#ifdef PIN_PA25 +extern const mcu_pin_obj_t pin_PA25; +#endif +#ifdef PIN_PB22 +extern const mcu_pin_obj_t pin_PB22; +#endif +#ifdef PIN_PB23 +extern const mcu_pin_obj_t pin_PB23; +#endif +#ifdef PIN_PA27 +extern const mcu_pin_obj_t pin_PA27; +#endif +#ifdef PIN_PA28 +extern const mcu_pin_obj_t pin_PA28; +#endif +#ifdef PIN_PA30 +extern const mcu_pin_obj_t pin_PA30; +#endif +#ifdef PIN_PA31 +extern const mcu_pin_obj_t pin_PA31; +#endif +#ifdef PIN_PB30 +extern const mcu_pin_obj_t pin_PB30; +#endif +#ifdef PIN_PB31 +extern const mcu_pin_obj_t pin_PB31; +#endif +#ifdef PIN_PB00 +extern const mcu_pin_obj_t pin_PB00; +#endif +#ifdef PIN_PB01 +extern const mcu_pin_obj_t pin_PB01; +#endif +#ifdef PIN_PB02 +extern const mcu_pin_obj_t pin_PB02; +#endif +#ifdef PIN_PB03 +extern const mcu_pin_obj_t pin_PB03; +#endif + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_BOARDS_SAMD21_PINS_H__ diff --git a/atmel-samd/samdneopixel.c b/atmel-samd/samdneopixel.c deleted file mode 100644 index 684188c1bb..0000000000 --- a/atmel-samd/samdneopixel.c +++ /dev/null @@ -1,113 +0,0 @@ -#include "asf/common2/services/delay/delay.h" -#include "asf/sam0/drivers/port/port.h" - -#include "mphalport.h" - -#include "samdneopixel.h" - -#ifdef MICROPY_HW_NEOPIXEL -static uint8_t status_neopixel_color[3]; -#endif - -extern void new_status_color(uint8_t r, uint8_t g, uint8_t b) { - #ifdef MICROPY_HW_NEOPIXEL - status_neopixel_color[0] = g; - status_neopixel_color[1] = r; - status_neopixel_color[2] = b; - samd_neopixel_write(MICROPY_HW_NEOPIXEL, status_neopixel_color, 3, true); - #endif -} -extern void temp_status_color(uint8_t r, uint8_t g, uint8_t b) { - #ifdef MICROPY_HW_NEOPIXEL - uint8_t colors[3] = {g, r, b}; - samd_neopixel_write(MICROPY_HW_NEOPIXEL, colors, 3, true); - #endif -} -extern void clear_temp_status() { - #ifdef MICROPY_HW_NEOPIXEL - samd_neopixel_write(MICROPY_HW_NEOPIXEL, status_neopixel_color, 3, true); - #endif -} - -void samd_neopixel_write(uint32_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz) { - // This is adapted directly from the Adafruit NeoPixel library SAMD21G18A code: - // https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp - uint8_t *ptr, *end, p, bitMask; - uint32_t pinMask; - PortGroup* port; - - // Turn off interrupts of any kind during timing-sensitive code. - mp_hal_disable_all_interrupts(); - - port = port_get_group_from_gpio_pin(pin); - pinMask = (1UL << (pin % 32)); // From port_pin_set_output_level ASF code. - ptr = pixels; - end = ptr + numBytes; - p = *ptr++; - bitMask = 0x80; - - volatile uint32_t *set = &(port->OUTSET.reg), - *clr = &(port->OUTCLR.reg); - - if(is800KHz) { - for(;;) { - *set = pinMask; - asm("nop; nop; nop; nop; nop; nop; nop; nop;"); - if(p & bitMask) { - asm("nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop;"); - *clr = pinMask; - } else { - *clr = pinMask; - asm("nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop;"); - } - if(bitMask >>= 1) { - asm("nop; nop; nop; nop; nop; nop; nop; nop; nop;"); - } else { - if(ptr >= end) break; - p = *ptr++; - bitMask = 0x80; - } - } - } else { // 400 KHz bitstream - for(;;) { - *set = pinMask; - asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"); - if(p & bitMask) { - asm("nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop;"); - *clr = pinMask; - } else { - *clr = pinMask; - asm("nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop;"); - } - asm("nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop; nop; nop; nop; nop;" - "nop; nop; nop; nop; nop; nop; nop; nop;"); - if(bitMask >>= 1) { - asm("nop; nop; nop; nop; nop; nop; nop;"); - } else { - if(ptr >= end) break; - p = *ptr++; - bitMask = 0x80; - } - } - } - - // Turn on interrupts after timing-sensitive code. - mp_hal_enable_all_interrupts(); - - // 50us delay to let pixels latch to the data that was just sent. - // This could be optimized to only occur before pixel writes when necessary, - // like in the Arduino library. - delay_us(50); -} diff --git a/atmel-samd/samdneopixel.h b/atmel-samd/samdneopixel.h deleted file mode 100644 index 0ebc080485..0000000000 --- a/atmel-samd/samdneopixel.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SAMD_NEOPIXEL_WRITE_H -#define SAMD_NEOPIXEL_WRITE_H - -#include -#include - -extern void new_status_color(uint8_t r, uint8_t g, uint8_t b); -extern void temp_status_color(uint8_t r, uint8_t g, uint8_t b); -extern void clear_temp_status(); - -void samd_neopixel_write(uint32_t pin, uint8_t *pixels, uint32_t numBytes, bool is800KHz); - -#endif diff --git a/atmel-samd/spi_flash.c b/atmel-samd/spi_flash.c index 6816757b40..332aee4f5a 100644 --- a/atmel-samd/spi_flash.c +++ b/atmel-samd/spi_flash.c @@ -36,7 +36,7 @@ #include "lib/fatfs/ff.h" #include "extmod/fsusermount.h" -#include "samdneopixel.h" +#include "neopixel_status.h" #define SPI_FLASH_PART1_START_BLOCK (0x1) @@ -78,17 +78,17 @@ static uint8_t** ram_cache; #define SCRATCH_SECTOR (flash_size - sector_size) // Enable the flash over SPI. -static void flash_enable() { +static void flash_enable(void) { port_pin_set_output_level(SPI_FLASH_CS, false); } // Disable the flash over SPI. -static void flash_disable() { +static void flash_disable(void) { port_pin_set_output_level(SPI_FLASH_CS, true); } // Wait until both the write enable and write in progress bits have cleared. -static bool wait_for_flash_ready() { +static bool wait_for_flash_ready(void) { uint8_t status_request[2] = {CMD_READ_STATUS, 0x00}; uint8_t response[2] = {0x00, 0x01}; enum status_code status = STATUS_OK; @@ -102,7 +102,7 @@ static bool wait_for_flash_ready() { } // Turn on the write enable bit so we can program and erase the flash. -static bool write_enable() { +static bool write_enable(void) { flash_enable(); uint8_t command = CMD_ENABLE_WRITE; enum status_code status = spi_write_buffer_wait(&spi_flash_instance, &command, 1); @@ -184,7 +184,7 @@ static bool erase_sector(uint32_t sector_address) { static bool copy_block(uint32_t src_address, uint32_t dest_address) { // Copy page by page to minimize RAM buffer. uint8_t buffer[page_size]; - for (int i = 0; i < FLASH_BLOCK_SIZE / page_size; i++) { + for (uint32_t i = 0; i < FLASH_BLOCK_SIZE / page_size; i++) { if (!read_flash(src_address + i * page_size, buffer, page_size)) { return false; } @@ -259,11 +259,11 @@ uint32_t spi_flash_get_block_count(void) { // Flush the cache that was written to the scratch portion of flash. Only used // when ram is tight. -static bool flush_scratch_flash() { +static bool flush_scratch_flash(void) { // First, copy out any blocks that we haven't touched from the sector we've // cached. bool copy_to_scratch_ok = true; - for (int i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { + for (uint8_t i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { if ((dirty_mask & (1 << i)) == 0) { copy_to_scratch_ok = copy_to_scratch_ok && copy_block(current_sector + i * FLASH_BLOCK_SIZE, @@ -278,7 +278,7 @@ static bool flush_scratch_flash() { // Second, erase the current sector. erase_sector(current_sector); // Finally, copy the new version into it. - for (int i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { + for (uint8_t i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { copy_block(SCRATCH_SECTOR + i * FLASH_BLOCK_SIZE, current_sector + i * FLASH_BLOCK_SIZE); } @@ -288,7 +288,7 @@ static bool flush_scratch_flash() { // Attempts to allocate a new set of page buffers for caching a full sector in // ram. Each page is allocated separately so that the GC doesn't need to provide // one huge block. We can free it as we write if we want to also. -static bool allocate_ram_cache() { +static bool allocate_ram_cache(void) { uint8_t blocks_per_sector = sector_size / FLASH_BLOCK_SIZE; uint8_t pages_per_block = FLASH_BLOCK_SIZE / page_size; ram_cache = gc_alloc(blocks_per_sector * pages_per_block * sizeof(uint32_t), false); @@ -297,11 +297,11 @@ static bool allocate_ram_cache() { } // Declare i and j outside the loops in case we fail to allocate everything // we need. In that case we'll give it back. - int i = 0; - int j = 0; + uint8_t i = 0; + uint8_t j = 0; bool success = true; - for (i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { - for (int j = 0; j < pages_per_block; j++) { + for (i = 0; i < blocks_per_sector; i++) { + for (j = 0; j < pages_per_block; j++) { uint8_t *page_cache = gc_alloc(page_size, false); if (page_cache == NULL) { success = false; @@ -315,11 +315,14 @@ static bool allocate_ram_cache() { } // We couldn't allocate enough so give back what we got. if (!success) { - for (; i >= 0; i--) { - for (; j >= 0; j--) { - gc_free(ram_cache[i * pages_per_block + j]); + // We add 1 so that we delete 0 when i is 1. Going to zero (i >= 0) + // would never stop because i is unsigned. + i++; + for (; i > 0; i--) { + for (; j > 0; j--) { + gc_free(ram_cache[(i - 1) * pages_per_block + (j - 1)]); } - j = pages_per_block - 1; + j = pages_per_block; } gc_free(ram_cache); ram_cache = NULL; @@ -335,9 +338,9 @@ static bool flush_ram_cache(bool keep_cache) { // erase below. bool copy_to_ram_ok = true; uint8_t pages_per_block = FLASH_BLOCK_SIZE / page_size; - for (int i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { + for (uint8_t i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { if ((dirty_mask & (1 << i)) == 0) { - for (int j = 0; j < pages_per_block; j++) { + for (uint8_t j = 0; j < pages_per_block; j++) { copy_to_ram_ok = read_flash( current_sector + (i * pages_per_block + j) * page_size, ram_cache[i * pages_per_block + j], @@ -358,8 +361,8 @@ static bool flush_ram_cache(bool keep_cache) { // Second, erase the current sector. erase_sector(current_sector); // Lastly, write all the data in ram that we've cached. - for (int i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { - for (int j = 0; j < pages_per_block; j++) { + for (uint8_t i = 0; i < sector_size / FLASH_BLOCK_SIZE; i++) { + for (uint8_t j = 0; j < pages_per_block; j++) { write_flash(current_sector + (i * pages_per_block + j) * page_size, ram_cache[i * pages_per_block + j], page_size); @@ -446,7 +449,7 @@ static void build_partition(uint8_t *buf, int boot, int type, buf[15] = num_blocks >> 24; } -static uint32_t convert_block_to_flash_addr(uint32_t block) { +static int32_t convert_block_to_flash_addr(uint32_t block) { if (SPI_FLASH_PART1_START_BLOCK <= block && block < spi_flash_get_block_count()) { // a block in partition 1 block -= SPI_FLASH_PART1_START_BLOCK; @@ -479,7 +482,7 @@ bool spi_flash_read_block(uint8_t *dest, uint32_t block) { return true; } else { // Non-MBR block, get data from flash memory. - uint32_t address = convert_block_to_flash_addr(block); + int32_t address = convert_block_to_flash_addr(block); if (address == -1) { // bad block number return false; @@ -514,7 +517,7 @@ bool spi_flash_write_block(const uint8_t *data, uint32_t block) { return true; } else { // Non-MBR block, copy to cache - uint32_t address = convert_block_to_flash_addr(block); + int32_t address = convert_block_to_flash_addr(block); if (address == -1) { // bad block number return false; @@ -573,6 +576,19 @@ mp_uint_t spi_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_ return 0; // success } +void mark_flash_cache_for_gc(void) { + if (current_sector != NO_SECTOR_LOADED && ram_cache != NULL) { + gc_mark_block(ram_cache); + uint8_t blocks_per_sector = sector_size / FLASH_BLOCK_SIZE; + uint8_t pages_per_block = FLASH_BLOCK_SIZE / page_size; + for (uint8_t i = 0; i < blocks_per_sector; i++) { + for (uint8_t j = 0; j < pages_per_block; j++) { + gc_mark_block(ram_cache[i * pages_per_block + j]); + } + } + } +} + /******************************************************************************/ // MicroPython bindings // diff --git a/atmel-samd/spi_flash.h b/atmel-samd/spi_flash.h index 8688928b40..f53fa4d118 100644 --- a/atmel-samd/spi_flash.h +++ b/atmel-samd/spi_flash.h @@ -48,6 +48,8 @@ bool spi_flash_write_block(const uint8_t *src, uint32_t block); mp_uint_t spi_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); mp_uint_t spi_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); +void mark_flash_cache_for_gc(void); + extern const struct _mp_obj_type_t spi_flash_type; struct _fs_user_mount_t; diff --git a/atmel-samd/tick.c b/atmel-samd/tick.c index bcbfcc0599..cad69f0807 100644 --- a/atmel-samd/tick.c +++ b/atmel-samd/tick.c @@ -5,7 +5,7 @@ #include "asf/sam0/drivers/tc/tc_interrupt.h" // Global millisecond tick count -volatile uint32_t ticks_ms = 0; +volatile uint64_t ticks_ms = 0; static struct tc_module ms_timer; @@ -13,9 +13,6 @@ static void ms_tick(struct tc_module *const module_inst) { // SysTick interrupt handler called when the SysTick timer reaches zero // (every millisecond). ticks_ms += 1; - // Keep the counter within the range of 31 bit uint values since that's the - // max value for micropython 'small' ints. - ticks_ms = ticks_ms > (0xFFFFFFFF >> 1) ? 0 : ticks_ms; #ifdef AUTORESET_DELAY_MS autoreset_tick(); diff --git a/atmel-samd/tick.h b/atmel-samd/tick.h index 731a691469..68e099ba06 100644 --- a/atmel-samd/tick.h +++ b/atmel-samd/tick.h @@ -28,8 +28,8 @@ #include "mpconfigport.h" -extern volatile uint32_t ticks_ms; +extern volatile uint64_t ticks_ms; -void tick_init(); +void tick_init(void); #endif // __MICROPY_INCLUDED_ATMEL_SAMD_TICK_H__ diff --git a/conf.py b/conf.py index da06f71a64..f9094886bb 100644 --- a/conf.py +++ b/conf.py @@ -87,7 +87,7 @@ exclude_patterns = ["*/build-*", "atmel-samd/asf", "atmel-samd/**.c", "atmel-sam # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +default_role = "any" # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True diff --git a/docs/common_hal.md b/docs/common_hal.md new file mode 100644 index 0000000000..9492699f40 --- /dev/null +++ b/docs/common_hal.md @@ -0,0 +1,70 @@ +# Adding `nativeio` support to other ports +`nativeio` provides a well-defined, cross-port hardware abstraction layer built to support different devices and their drivers. It's backed by the Common HAL, a C api suitable for supporting different hardware in a similar manner. By sharing this C api, developers can support new hardware easily and cross-port functionality to the new hardware. + +## File layout +Common HAL related files are found in these locations: + +* `shared-bindings` Shared home for the Python <-> C bindings which includes inline RST documentation for the created interfaces. The common hal functions are defined in the .h files of the corresponding C files. +* `shared-modules` Shared home for C code built on the Common HAL and used by all ports. This code only uses `common_hal` methods defined in `shared-bindings`. +* `/common-hal` Port-specific implementation of the Common HAL. + +Each folder has the substructure of / and they should match 1:1. `__init__.c` is used for module globals that are not classes (similar to `__init__.py`). + +## Adding support + +### Modifying the build +The first step is to hook the `shared-bindings` into your build for the modules you wish to support. Here's an example of this step for the `atmel-samd/Makefile`: + +``` +SRC_BINDINGS = \ + board/__init__.c \ + microcontroller/__init__.c \ + microcontroller/Pin.c \ + nativeio/__init__.c \ + nativeio/AnalogIn.c \ + nativeio/AnalogOut.c \ + nativeio/DigitalInOut.c \ + nativeio/I2C.c \ + nativeio/PWMOut.c \ + nativeio/SPI.c \ + neopixel_write/__init__.c \ + time/__init__.c + +SRC_BINDINGS_EXPANDED = $(addprefix shared-bindings/, $(SRC_BINDINGS)) \ + $(addprefix common-hal/, $(SRC_BINDINGS)) + +# Add the resulting objects to the full list +OBJ += $(addprefix $(BUILD)/, $(SRC_BINDINGS_EXPANDED:.c=.o)) +# Add the sources for QSTR generation +SRC_QSTR += $(SRC_C) $(SRC_BINDINGS_EXPANDED) $(STM_SRC_C) +``` + +The `Makefile` defines the modules to build and adds the sources to include the `shared-bindings` version and the `common-hal` version within the port specific directory. You may comment out certain subfolders to reduce the number of modules to add but don't comment out individual classes. It won't compile then. + +### Hooking the modules in +Built in modules are typically defined in `mpconfigport.h`. To add support you should have something like: + +``` +extern const struct _mp_obj_module_t microcontroller_module; +extern const struct _mp_obj_module_t nativeio_module; +extern const struct _mp_obj_module_t board_module; +extern const struct _mp_obj_module_t time_module; +extern const struct _mp_obj_module_t neopixel_write_module; + +#define MICROPY_PORT_BUILTIN_MODULES \ + { MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)µcontroller_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_nativeio), (mp_obj_t)&nativeio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module } \ +``` + +### Implementing the Common HAL +At this point in the port, nothing will compile yet, because there's still work to be done to fix missing sources, compile issues, and link issues. I suggest start with a common-hal directory from another port that implements it such as `atmel-samd` or `esp8266`, deleting the function contents and stubbing out any return statements. Once that is done, you should be able to compile cleanly and import the modules, but nothing will work (though you are getting closer). + +The last step is actually implementing each function in a port specific way. I can't help you with this. :-) If you have any questions how a Common HAL function should work then see the corresponding .h file in `shared-bindings`. + +### Testing +Woohoo! You are almost done. After you implement everything, lots of drivers and sample code should just work. There are a number of drivers and examples written for Adafruit's Feather ecosystem. Here are places to start: + +* https://github.com/adafruit?utf8=%E2%9C%93&q=Adafruit_MicroPython&type=&language= diff --git a/docs/supported_ports.rst b/docs/supported_ports.rst index 981a1cd3e2..c8febefe13 100644 --- a/docs/supported_ports.rst +++ b/docs/supported_ports.rst @@ -8,3 +8,4 @@ the Atmel SAMD21 port :maxdepth: 2 ../atmel-samd/README + esp8266/index.rst diff --git a/docs/unsupported_ports.rst b/docs/unsupported_ports.rst index 7ace37155c..e04537656b 100644 --- a/docs/unsupported_ports.rst +++ b/docs/unsupported_ports.rst @@ -10,6 +10,5 @@ We recommend using `upstream MicroPython `_ for the bel .. toctree:: :maxdepth: 2 - esp8266/index.rst pyboard/index.rst wipy/index.rst diff --git a/esp8266/Makefile b/esp8266/Makefile index b2191353a2..45ab401dd5 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -1,5 +1,15 @@ include ../py/mkenv.mk +# Select the board to build for: if not given on the command line, +# then default to PYBV10. +BOARD ?= feather_huzzah +ifeq ($(wildcard boards/$(BOARD)/.),) +$(error Invalid BOARD specified) +endif + +# If the build directory is not given, make it reflect the board name. +BUILD ?= build-$(BOARD) + # qstr definitions (must come before including py.mk) QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h @@ -93,8 +103,34 @@ SRC_C = \ fatfs_port.c \ axtls_helpers.c \ hspi.c \ + boards/$(BOARD)/pins.c \ $(SRC_MOD) +SRC_COMMON_HAL = \ + microcontroller/__init__.c \ + microcontroller/Pin.c \ + nativeio/__init__.c \ + nativeio/AnalogIn.c \ + nativeio/AnalogOut.c \ + nativeio/DigitalInOut.c \ + nativeio/I2C.c \ + nativeio/PWMOut.c \ + nativeio/SPI.c \ + neopixel_write/__init__.c \ + time/__init__.c \ + board/__init__.c + +SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ + $(addprefix common-hal/, $(SRC_COMMON_HAL)) + +SRC_SHARED_MODULE = \ + bitbangio/__init__.c \ + bitbangio/I2C.c \ + bitbangio/SPI.c \ + +SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ + $(addprefix shared-module/, $(SRC_SHARED_MODULE)) + STM_SRC_C = $(addprefix stmhal/,\ pybstdio.c \ input.c \ @@ -149,6 +185,8 @@ OBJ = OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_EXPANDED:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o)) @@ -156,7 +194,7 @@ OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o)) #OBJ += $(BUILD)/pins_$(BOARD).o # List of sources for qstr extraction -SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C) +SRC_QSTR += $(SRC_C) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(STM_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C) # Append any auto-generated sources that are needed by sources listed in SRC_QSTR SRC_QSTR_AUTO_DEPS += diff --git a/esp8266/boards/feather_huzzah/pins.c b/esp8266/boards/feather_huzzah/pins.c new file mode 100644 index 0000000000..c685553929 --- /dev/null +++ b/esp8266/boards/feather_huzzah/pins.c @@ -0,0 +1,48 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 "common-hal/microcontroller/__init__.h" + +STATIC const mp_map_elem_t board_global_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pin_TOUT }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO16), (mp_obj_t)&pin_XPD_DCDC }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO14), (mp_obj_t)&pin_MTMS }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_MTMS }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO12), (mp_obj_t)&pin_MTDI }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_MTDI }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO13), (mp_obj_t)&pin_MTCK }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_MTCK }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO15), (mp_obj_t)&pin_MTDO }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO2), (mp_obj_t)&pin_GPIO2 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO0), (mp_obj_t)&pin_GPIO0 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO4), (mp_obj_t)&pin_GPIO4 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_GPIO4 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_RX), (mp_obj_t)&pin_U0RXD }, + { MP_OBJ_NEW_QSTR(MP_QSTR_TX), (mp_obj_t)&pin_U0TXD }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO5), (mp_obj_t)&pin_DVDD }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_DVDD }, +}; +MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table); diff --git a/atmel-samd/modmachine_pwm.h b/esp8266/common-hal/board/__init__.c similarity index 84% rename from atmel-samd/modmachine_pwm.h rename to esp8266/common-hal/board/__init__.c index 1989b6e52e..3893e70f7f 100644 --- a/atmel-samd/modmachine_pwm.h +++ b/esp8266/common-hal/board/__init__.c @@ -24,4 +24,11 @@ * THE SOFTWARE. */ -extern const mp_obj_type_t pwm_type; +#include + +#include "py/runtime.h" +#include "py/mphal.h" +#include "common-hal/microcontroller/types.h" + +// Pins aren't actually defined here. They are in the board specific directory +// such as boards/feather_huzzah/pins.c. diff --git a/esp8266/common-hal/microcontroller/Pin.c b/esp8266/common-hal/microcontroller/Pin.c new file mode 100644 index 0000000000..2e8b72a2c0 --- /dev/null +++ b/esp8266/common-hal/microcontroller/Pin.c @@ -0,0 +1 @@ +// Pins have no behavior. diff --git a/esp8266/common-hal/microcontroller/__init__.c b/esp8266/common-hal/microcontroller/__init__.c new file mode 100644 index 0000000000..09ea920677 --- /dev/null +++ b/esp8266/common-hal/microcontroller/__init__.c @@ -0,0 +1,94 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 "common-hal/microcontroller/types.h" +#include "shared-bindings/microcontroller/Pin.h" + +#include "eagle_soc.h" +#include "osapi.h" +#include "etshal.h" + +void common_hal_mcu_delay_us(uint32_t delay) { + os_delay_us(delay); +} + +// This macro is used to simplify pin definition in boards//pins.c +#define PIN(p_name, p_gpio_number, p_gpio_function, p_peripheral) \ +const mcu_pin_obj_t pin_## p_name = { \ + { &mcu_pin_type }, \ + .name = MP_QSTR_ ## p_name, \ + .gpio_number = p_gpio_number, \ + .gpio_function = p_gpio_function, \ + .peripheral = p_peripheral, \ +} + +#define NO_GPIO 0xff +#define SPECIAL_CASE 0xfe + +// Using microcontroller names from the datasheet. +// https://cdn-shop.adafruit.com/datasheets/ESP8266_Specifications_English.pdf +// PIN(mcu name) // function notes | module name | huzzah name +PIN(TOUT, NO_GPIO, NO_GPIO, NO_GPIO); // adc | ADC | ADC +PIN(XPD_DCDC, 16, SPECIAL_CASE, SPECIAL_CASE); // gpio16 | GPIO16 | GPIO16 +PIN(MTMS, 14, FUNC_GPIO14, PERIPHS_IO_MUX_MTMS_U); // gpio14 / hspi_clk / pwm2 | GPIO14 | GPIO14/SCK +PIN(MTDI, 12, FUNC_GPIO12, PERIPHS_IO_MUX_MTDI_U); // gpio12 / hspi_miso / pwm0 | GPIO12 | GPIO12/MISO +PIN(MTCK, 13, FUNC_GPIO13, PERIPHS_IO_MUX_MTCK_U); // gpio13 / hspi_mosi / U0cts | GPIO13 | GPIO13/MOSI +PIN(MTDO, 15, FUNC_GPIO15, PERIPHS_IO_MUX_MTDO_U); // gpio15 / hspi_cs / u0rts / pwm1 | GPIO15 | GPIO15 +PIN(GPIO2, 2, FUNC_GPIO2, PERIPHS_IO_MUX_GPIO2_U); // U1txd | GPIO2 | GPIO2 +PIN(GPIO0, 0, FUNC_GPIO0, PERIPHS_IO_MUX_GPIO0_U); // spi_Cs2 | GPIO0 | GPIO0 +PIN(GPIO4, 4, FUNC_GPIO4, PERIPHS_IO_MUX_GPIO4_U); // pwm3 on mcu datasheet as vdd which must be wrong | GPIO4 | GPIO4/SDA +PIN(SD_DATA_2, 9, FUNC_GPIO9, PERIPHS_IO_MUX_SD_DATA2_U); // spihd / hspihd / gpio9 | GPIO9 +PIN(SD_DATA_3, 10, FUNC_GPIO10, PERIPHS_IO_MUX_SD_DATA3_U); // spiwp / hspiwp / gpio10 | GPIO10 +PIN(SD_CMD, NO_GPIO, NO_GPIO, PERIPHS_IO_MUX_SD_CMD_U); // spi_cs0 / gpio11 | CS0 +PIN(SD_CLK, NO_GPIO, NO_GPIO, PERIPHS_IO_MUX_SD_CLK_U); // spi_clk / gpio6 | SCLK +PIN(SD_DATA_0, NO_GPIO, NO_GPIO, PERIPHS_IO_MUX_SD_DATA0_U); // spi_miso / gpio7 | MISO +PIN(SD_DATA_1, NO_GPIO, NO_GPIO, PERIPHS_IO_MUX_SD_DATA1_U); // spi_mosi / gpio8 / u1rxd | MOSI +PIN(DVDD, 5, FUNC_GPIO5, PERIPHS_IO_MUX_GPIO5_U); // gpio5 | GPIO5 | GPIO5/SCL +PIN(U0RXD, 3, FUNC_GPIO3, PERIPHS_IO_MUX_U0RXD_U); // gpio3 | RXD0 | RXD +PIN(U0TXD, 1, FUNC_GPIO1, PERIPHS_IO_MUX_U0TXD_U); // gpio1 / spi_cs1 | TXD0 | TXD + +// This maps MCU pin names to pin objects. +STATIC const mp_map_elem_t mcu_pin_global_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_TOUT), (mp_obj_t)&pin_TOUT }, + { MP_OBJ_NEW_QSTR(MP_QSTR_XPD_DCDC), (mp_obj_t)&pin_XPD_DCDC }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTMS), (mp_obj_t)&pin_MTMS }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTDI), (mp_obj_t)&pin_MTDI }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTCK), (mp_obj_t)&pin_MTCK }, + { MP_OBJ_NEW_QSTR(MP_QSTR_MTDO), (mp_obj_t)&pin_MTDO }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO2), (mp_obj_t)&pin_GPIO2 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO0), (mp_obj_t)&pin_GPIO0 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_GPIO4), (mp_obj_t)&pin_GPIO4 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_DATA_2), (mp_obj_t)&pin_SD_DATA_2 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_DATA_3), (mp_obj_t)&pin_SD_DATA_3 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CMD), (mp_obj_t)&pin_SD_CMD }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_CLK), (mp_obj_t)&pin_SD_CLK }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_DATA_0), (mp_obj_t)&pin_SD_DATA_0 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SD_DATA_1), (mp_obj_t)&pin_SD_DATA_1 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_DVDD), (mp_obj_t)&pin_DVDD }, + { MP_OBJ_NEW_QSTR(MP_QSTR_U0RXD), (mp_obj_t)&pin_U0RXD }, + { MP_OBJ_NEW_QSTR(MP_QSTR_U0TXD), (mp_obj_t)&pin_U0TXD }, +}; +MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table); diff --git a/esp8266/common-hal/microcontroller/__init__.h b/esp8266/common-hal/microcontroller/__init__.h new file mode 100644 index 0000000000..c82df49e99 --- /dev/null +++ b/esp8266/common-hal/microcontroller/__init__.h @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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_ESP8266_COMMON_HAL_MICROCONTROLLER___INIT___H__ + #define __MICROPY_INCLUDED_ESP8266_COMMON_HAL_MICROCONTROLLER___INIT___H__ + +#include "common-hal/microcontroller/types.h" + +extern const mcu_pin_obj_t pin_TOUT; +extern const mcu_pin_obj_t pin_XPD_DCDC; +extern const mcu_pin_obj_t pin_MTMS; +extern const mcu_pin_obj_t pin_MTDI; +extern const mcu_pin_obj_t pin_MTCK; +extern const mcu_pin_obj_t pin_MTDO; +extern const mcu_pin_obj_t pin_GPIO2; +extern const mcu_pin_obj_t pin_GPIO0; +extern const mcu_pin_obj_t pin_GPIO4; +extern const mcu_pin_obj_t pin_SD_DATA_2; +extern const mcu_pin_obj_t pin_SD_DATA_3; +extern const mcu_pin_obj_t pin_SD_CMD; +extern const mcu_pin_obj_t pin_SD_CLK; +extern const mcu_pin_obj_t pin_SD_DATA_0; +extern const mcu_pin_obj_t pin_SD_DATA_1; +extern const mcu_pin_obj_t pin_DVDD; +extern const mcu_pin_obj_t pin_U0RXD; +extern const mcu_pin_obj_t pin_U0TXD; + +#endif // __MICROPY_INCLUDED_ESP8266_COMMON_HAL_MICROCONTROLLER___INIT___H__ diff --git a/esp8266/common-hal/microcontroller/types.h b/esp8266/common-hal/microcontroller/types.h new file mode 100644 index 0000000000..8245cd303e --- /dev/null +++ b/esp8266/common-hal/microcontroller/types.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_COMMON_HAL_MICROCONTROLLER_TYPES_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__ + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + qstr name; + uint8_t gpio_number; + uint8_t gpio_function; + uint32_t peripheral; +} mcu_pin_obj_t; + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__ diff --git a/esp8266/common-hal/nativeio/AnalogIn.c b/esp8266/common-hal/nativeio/AnalogIn.c new file mode 100644 index 0000000000..efdd2d2ac7 --- /dev/null +++ b/esp8266/common-hal/nativeio/AnalogIn.c @@ -0,0 +1,45 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 +#include + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/binary.h" +#include "py/mphal.h" +#include "shared-bindings/nativeio/AnalogIn.h" + +#include "user_interface.h" + +void common_hal_nativeio_analogin_construct(nativeio_analogin_obj_t* self, + const mcu_pin_obj_t *pin) { +} + +uint16_t common_hal_nativeio_analogin_get_value(nativeio_analogin_obj_t *self) { + // ADC is 10 bit so shift by 6 to make it 16-bit. + return system_adc_read() << 6; +} diff --git a/atmel-samd/pin_named_pins.c b/esp8266/common-hal/nativeio/AnalogOut.c similarity index 57% rename from atmel-samd/pin_named_pins.c rename to esp8266/common-hal/nativeio/AnalogOut.c index 24406f1905..06b1880c34 100644 --- a/atmel-samd/pin_named_pins.c +++ b/esp8266/common-hal/nativeio/AnalogOut.c @@ -25,36 +25,23 @@ */ #include +#include #include #include "py/runtime.h" -#include "py/mphal.h" -#include "modmachine_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, "", self->name); +#include "shared-bindings/nativeio/AnalogOut.h" + + +void common_hal_nativeio_analogout_construct(nativeio_analogout_obj_t* self, + const mcu_pin_obj_t *pin) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "No hardware support for analog out.")); } -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; +void common_hal_nativeio_analogout_deinit(nativeio_analogout_obj_t *self) { +} + +void common_hal_nativeio_analogout_set_value(nativeio_analogout_obj_t *self, + uint16_t value) { } diff --git a/esp8266/common-hal/nativeio/DigitalInOut.c b/esp8266/common-hal/nativeio/DigitalInOut.c new file mode 100644 index 0000000000..d933864c4c --- /dev/null +++ b/esp8266/common-hal/nativeio/DigitalInOut.c @@ -0,0 +1,174 @@ +/* + * 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 +#include +#include + +#include "py/nlr.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "shared-bindings/nativeio/DigitalInOut.h" + +digitalinout_result_t common_hal_nativeio_digitalinout_construct( + nativeio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin) { + self->pin = pin; + PIN_FUNC_SELECT(self->pin->peripheral, self->pin->gpio_function); + return DIGITALINOUT_OK; +} + +void common_hal_nativeio_digitalinout_deinit(nativeio_digitalinout_obj_t* self) { + uint32_t pin_mask = 1 << self->pin->gpio_number; + gpio_output_set(0x0, 0x0, 0x0, pin_mask); +} + +void common_hal_nativeio_digitalinout_switch_to_input( + nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull) { + self->output = false; + + if (self->pin->gpio_number == 16) { + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); + WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input + } else { + PIN_PULLUP_DIS(self->pin->peripheral); + gpio_output_set(0, 0, 0, 1 << self->pin->gpio_number); + } + common_hal_nativeio_digitalinout_set_pull(self, pull); +} + +void common_hal_nativeio_digitalinout_switch_to_output( + nativeio_digitalinout_obj_t* self, bool value, + enum digitalinout_drive_mode_t drive_mode) { + self->output = true; + self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; + if (self->pin->gpio_number == 16) { + WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1); + WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1); + WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); // output + } else if (!self->open_drain) { + gpio_output_set(0, 0, 1 << self->pin->gpio_function, 0); + PIN_PULLUP_DIS(self->pin->peripheral); + } + common_hal_nativeio_digitalinout_set_value(self, value); +} + +enum digitalinout_direction_t common_hal_nativeio_digitalinout_get_direction( + nativeio_digitalinout_obj_t* self) { + return self->output? DIRECTION_OUT : DIRECTION_IN; +} + +void common_hal_nativeio_digitalinout_set_value( + nativeio_digitalinout_obj_t* self, bool value) { + if (value) { + if (self->open_drain) { + // Disable output. + gpio_output_set(0, 0, 0, 1 << self->pin->gpio_number); + PIN_PULLUP_EN(self->pin->peripheral); + } else { + // Set high + gpio_output_set(1 << self->pin->gpio_number, 0, 0, 0); + } + } else { + if (self->open_drain) { + // Enable the output + PIN_PULLUP_DIS(self->pin->peripheral); + gpio_output_set(0, 0, 1 << self->pin->gpio_number, 0); + } + // Set low + gpio_output_set(0, 1 << self->pin->gpio_number, 0, 0); + } +} + +// Register addresses taken from: https://github.com/esp8266/esp8266-wiki/wiki/gpio-registers +volatile uint32_t* PIN_DIR = (uint32_t *) 0x6000030C; +volatile uint32_t* PIN_OUT = (uint32_t *) 0x60000300; +bool common_hal_nativeio_digitalinout_get_value( + nativeio_digitalinout_obj_t* self) { + if (!self->output) { + if (self->pin->gpio_number == 16) { + return READ_PERI_REG(RTC_GPIO_IN_DATA) & 1; + } + return GPIO_INPUT_GET(self->pin->gpio_number); + } else { + uint32_t pin_mask = 1 << self->pin->gpio_number; + if (self->open_drain && ((*PIN_DIR) & pin_mask) == 0) { + return true; + } else { + return ((*PIN_OUT) & pin_mask) != 0; + } + } +} + +void common_hal_nativeio_digitalinout_set_drive_mode( + nativeio_digitalinout_obj_t* self, + enum digitalinout_drive_mode_t drive_mode) { + bool value = common_hal_nativeio_digitalinout_get_value(self); + self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN; + // True is implemented differently between modes so reset the value to make + // sure its correct for the new mode. + if (value) { + common_hal_nativeio_digitalinout_set_value(self, value); + } +} + +enum digitalinout_drive_mode_t common_hal_nativeio_digitalinout_get_drive_mode( + nativeio_digitalinout_obj_t* self) { + if (self->open_drain) { + return DRIVE_MODE_OPEN_DRAIN; + } else { + return DRIVE_MODE_PUSH_PULL; + } +} + +void common_hal_nativeio_digitalinout_set_pull( + nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull) { + if (pull == PULL_DOWN) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "ESP8266 does not support pull down.")); + return; + } + if (self->pin->gpio_number == 16) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Pin does not support pull.")); + return; + } + if (pull == PULL_NONE) { + PIN_PULLUP_DIS(self->pin->peripheral); + } else { + PIN_PULLUP_EN(self->pin->peripheral); + } +} + +enum digitalinout_pull_t common_hal_nativeio_digitalinout_get_pull( + nativeio_digitalinout_obj_t* self) { + if (self->pin->gpio_number < 16 && + (READ_PERI_REG(self->pin->peripheral) & PERIPHS_IO_MUX_PULLUP) != 0) { + return PULL_UP; + } + return PULL_NONE; +} diff --git a/esp8266/common-hal/nativeio/I2C.c b/esp8266/common-hal/nativeio/I2C.c new file mode 100644 index 0000000000..2307686e23 --- /dev/null +++ b/esp8266/common-hal/nativeio/I2C.c @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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 "shared-bindings/nativeio/I2C.h" +#include "py/nlr.h" + +void common_hal_nativeio_i2c_construct(nativeio_i2c_obj_t *self, + const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t freq) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "No hardware support for I2C. Use bitbangio instead.")); +} + +void common_hal_nativeio_i2c_deinit(nativeio_i2c_obj_t *self) { +} + +bool common_hal_nativeio_i2c_probe(nativeio_i2c_obj_t *self, uint8_t addr) { + return false; +} + +bool common_hal_nativeio_i2c_write(nativeio_i2c_obj_t *self, uint16_t addr, + const uint8_t * data, size_t len, bool transmit_stop_bit) { + return false; +} + +bool common_hal_nativeio_i2c_read(nativeio_i2c_obj_t *self, uint16_t addr, + uint8_t * data, size_t len) { + return false; +} diff --git a/esp8266/common-hal/nativeio/PWMOut.c b/esp8266/common-hal/nativeio/PWMOut.c new file mode 100644 index 0000000000..c12bc7cf2b --- /dev/null +++ b/esp8266/common-hal/nativeio/PWMOut.c @@ -0,0 +1,67 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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 +#include + +#include "esppwm.h" + +#include "py/runtime.h" +#include "shared-bindings/nativeio/PWMOut.h" + +// Shared with pybpwm +extern bool pwm_inited; + +void common_hal_nativeio_pwmout_construct(nativeio_pwmout_obj_t* self, const mcu_pin_obj_t* pin, uint16_t duty) { + // start the PWM subsystem if it's not already running + if (!pwm_inited) { + pwm_init(); + pwm_inited = true; + } + + self->channel = pwm_add(pin->gpio_number, + pin->peripheral, + pin->gpio_function); + if (self->channel == -1) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "PWM not supported on pin %d", pin->gpio_number)); + } +} + +extern void common_hal_nativeio_pwmout_deinit(nativeio_pwmout_obj_t* self) { + pwm_delete(self->channel); + pwm_start(); +} + +extern void common_hal_nativeio_pwmout_set_duty_cycle(nativeio_pwmout_obj_t* self, uint16_t duty) { + // We get 16 bits of duty in but the underlying code is only ten bit. + pwm_set_duty(duty >> 6, self->channel); + pwm_start(); +} + +uint16_t common_hal_nativeio_pwmout_get_duty_cycle(nativeio_pwmout_obj_t* self) { + return pwm_get_duty(self->channel) << 6; +} diff --git a/esp8266/common-hal/nativeio/SPI.c b/esp8266/common-hal/nativeio/SPI.c new file mode 100644 index 0000000000..c517dd125b --- /dev/null +++ b/esp8266/common-hal/nativeio/SPI.c @@ -0,0 +1,90 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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 "esp8266/ets_alt_task.h" +#include "esp8266/hspi.h" +#include "shared-bindings/nativeio/SPI.h" +#include "py/nlr.h" + +#include "eagle_soc.h" + +extern const mcu_pin_obj_t pin_MTMS; +extern const mcu_pin_obj_t pin_MTCK; +extern const mcu_pin_obj_t pin_MTDI; + +void common_hal_nativeio_spi_construct(nativeio_spi_obj_t *self, + const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, + const mcu_pin_obj_t * miso, uint32_t baudrate) { + if (clock != &pin_MTMS || mosi != &pin_MTCK || miso != &pin_MTDI) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Pins not valid for SPI")); + } +} + +void common_hal_nativeio_spi_deinit(nativeio_spi_obj_t *self) { + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 0); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 0); +} + +bool common_hal_nativeio_spi_write(nativeio_spi_obj_t *self, + const uint8_t * data, size_t len) { + size_t chunk_size = 1024; + size_t count = len / chunk_size; + size_t i = 0; + for (size_t j = 0; j < count; ++j) { + for (size_t k = 0; k < chunk_size; ++k) { + spi_tx8fast(HSPI, data[i]); + ++i; + } + ets_loop_iter(); + } + while (i < len) { + spi_tx8fast(HSPI, data[i]); + ++i; + } + return true; +} + +bool common_hal_nativeio_spi_read(nativeio_spi_obj_t *self, + uint8_t * data, size_t len) { + // Process data in chunks, let the pending tasks run in between + size_t chunk_size = 1024; // TODO this should depend on baudrate + size_t count = len / chunk_size; + size_t i = 0; + for (size_t j = 0; j < count; ++j) { + for (size_t k = 0; k < chunk_size; ++k) { + data[i] = spi_rx8(HSPI); + ++i; + } + ets_loop_iter(); + } + while (i < len) { + data[i] = spi_rx8(HSPI); + ++i; + } + return true; +} diff --git a/esp8266/common-hal/nativeio/__init__.c b/esp8266/common-hal/nativeio/__init__.c new file mode 100644 index 0000000000..e0ec8acfb1 --- /dev/null +++ b/esp8266/common-hal/nativeio/__init__.c @@ -0,0 +1 @@ +// No nativeio module functions. diff --git a/esp8266/common-hal/nativeio/types.h b/esp8266/common-hal/nativeio/types.h new file mode 100644 index 0000000000..7cc18fd251 --- /dev/null +++ b/esp8266/common-hal/nativeio/types.h @@ -0,0 +1,68 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// This defines the types used to underly the standard nativeio Python objects. +// The shared API is defined in terms of these types. + +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__ + +#include "common-hal/microcontroller/types.h" + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t * pin; +} nativeio_analogin_obj_t; + +// Not supported, throws error on construction. +typedef struct { + mp_obj_base_t base; +} nativeio_analogout_obj_t; + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t * pin; + bool output; + bool open_drain; +} nativeio_digitalinout_obj_t; + +// Not supported, throws error on construction. +typedef struct { + mp_obj_base_t base; +} nativeio_i2c_obj_t; + +typedef struct { + mp_obj_base_t base; +} nativeio_spi_obj_t; + +typedef struct { + mp_obj_base_t base; + int channel; +} nativeio_pwmout_obj_t; + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__ diff --git a/esp8266/common-hal/neopixel_write/__init__.c b/esp8266/common-hal/neopixel_write/__init__.c new file mode 100644 index 0000000000..efc161256d --- /dev/null +++ b/esp8266/common-hal/neopixel_write/__init__.c @@ -0,0 +1,33 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 "shared-bindings/neopixel_write/__init__.h" + +#include "espneopixel.h" + +void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes, bool is800KHz) { + esp_neopixel_write(digitalinout->pin->gpio_number, pixels, numBytes, is800KHz); +} diff --git a/esp8266/common-hal/time/__init__.c b/esp8266/common-hal/time/__init__.c new file mode 100644 index 0000000000..993e89b1c3 --- /dev/null +++ b/esp8266/common-hal/time/__init__.c @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 "py/mphal.h" + +#include "shared-bindings/time/__init__.h" + +#include "ets_alt_task.h" +#include "user_interface.h" + +inline uint64_t common_hal_time_monotonic() { + return ((uint64_t)system_time_high_word << 32 | (uint64_t)system_get_time()) / 1000; +} + +void common_hal_time_delay_ms(uint32_t delay) { + mp_hal_delay_ms(delay); +} diff --git a/esp8266/esp8266.ld b/esp8266/esp8266.ld index 20b259dff2..d1773cba1a 100644 --- a/esp8266/esp8266.ld +++ b/esp8266/esp8266.ld @@ -80,6 +80,9 @@ SECTIONS *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text) /* we put some specific text in this section */ + *common-hal/*.o*(.literal* .text*) + *shared-bindings/*.o*(.literal* .text*) + *shared-module/*.o*(.literal* .text*) *py/argcheck.o*(.literal* .text*) *py/asm*.o*(.literal* .text*) diff --git a/esp8266/ets_alt_task.h b/esp8266/ets_alt_task.h index dba0c5fa64..d00898a783 100644 --- a/esp8266/ets_alt_task.h +++ b/esp8266/ets_alt_task.h @@ -1,4 +1,12 @@ +#ifndef _INCLUDED_ETS_ALT_TASK_H_ +#define _INCLUDED_ETS_ALT_TASK_H_ + +#include +#include + extern int ets_loop_iter_disable; extern uint32_t system_time_high_word; bool ets_loop_iter(void); + +#endif // _INCLUDED_ETS_ALT_TASK_H_ diff --git a/esp8266/machine_pwm.c b/esp8266/machine_pwm.c index 5d30f09656..4de7edfb9d 100644 --- a/esp8266/machine_pwm.c +++ b/esp8266/machine_pwm.c @@ -40,7 +40,7 @@ typedef struct _pyb_pwm_obj_t { uint8_t channel; } pyb_pwm_obj_t; -STATIC bool pwm_inited = false; +bool pwm_inited = false; /******************************************************************************/ // MicroPython bindings for PWM diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h index 602b3e9c81..dbfe24afd3 100644 --- a/esp8266/mpconfigport.h +++ b/esp8266/mpconfigport.h @@ -98,6 +98,7 @@ #define MICROPY_ESP8266_APA102 (1) #define MICROPY_ESP8266_NEOPIXEL (1) +extern void ets_event_poll(void); #define MICROPY_EVENT_POLL_HOOK {ets_event_poll();} #define MICROPY_VM_HOOK_COUNT (10) #define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT; @@ -146,6 +147,11 @@ extern const struct _mp_obj_module_t uos_module; extern const struct _mp_obj_module_t mp_module_lwip; extern const struct _mp_obj_module_t mp_module_machine; extern const struct _mp_obj_module_t onewire_module; +extern const struct _mp_obj_module_t microcontroller_module; +extern const struct _mp_obj_module_t board_module; +extern const struct _mp_obj_module_t nativeio_module; +extern const struct _mp_obj_module_t bitbangio_module; +extern const struct _mp_obj_module_t time_module; #define MICROPY_PORT_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \ @@ -157,9 +163,13 @@ extern const struct _mp_obj_module_t onewire_module; { MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \ { MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&onewire_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)µcontroller_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_nativeio), (mp_obj_t)&nativeio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \ #define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \ - { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&uos_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \ diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c index 8e05809662..571acabfe7 100644 --- a/extmod/modwebrepl.c +++ b/extmod/modwebrepl.c @@ -40,7 +40,7 @@ #include "extmod/modwebsocket.h" #include "genhdr/mpversion.h" -#if MICROPY_PY_WEBREPL +#ifdef MICROPY_PY_WEBREPL #if 0 // print debugging info #define DEBUG_printf DEBUG_printf diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c index d888099dff..926a2bf0f6 100644 --- a/extmod/uos_dupterm.c +++ b/extmod/uos_dupterm.c @@ -34,7 +34,7 @@ #include "py/objarray.h" #include "py/stream.h" -#if MICROPY_PY_OS_DUPTERM +#ifdef MICROPY_PY_OS_DUPTERM void mp_uos_deactivate(const char *msg, mp_obj_t exc) { mp_obj_t term = MP_STATE_PORT(term_obj); diff --git a/index.rst b/index.rst index 09194211ec..e1b9112492 100644 --- a/index.rst +++ b/index.rst @@ -11,7 +11,7 @@ educational development boards designed and sold by `Adafruit `_. Adafruit's MicroPython port features a unified Python APIs available under -`shared-bindings` and a growing list of drivers that work with it. Currently +`!shared-bindings` and a growing list of drivers that work with it. Currently only the Atmel SAMD21 port is supported but ESP8266 support will be added in the near future. @@ -23,6 +23,7 @@ docs are low-level API docs and may link out to separate getting started guides. :maxdepth: 2 shared-bindings/index.rst + docs/common_hal docs/drivers.rst docs/supported_ports.rst docs/unsupported_ports.rst diff --git a/lib/libc/string0.c b/lib/libc/string0.c index 1b37169edd..b906725dcf 100644 --- a/lib/libc/string0.c +++ b/lib/libc/string0.c @@ -29,6 +29,8 @@ #define likely(x) __builtin_expect((x), 1) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" void *memcpy(void *dst, const void *src, size_t n) { if (likely(!(((uintptr_t)dst) & 3) && !(((uintptr_t)src) & 3))) { // pointers aligned @@ -102,6 +104,8 @@ void *memset(void *s, int c, size_t n) { return s; } +#pragma GCC diagnostic pop + int memcmp(const void *s1, const void *s2, size_t n) { const uint8_t *s1_8 = s1; const uint8_t *s2_8 = s2; diff --git a/py/argcheck.c b/py/argcheck.c index 8cef10b165..e12800a36b 100644 --- a/py/argcheck.c +++ b/py/argcheck.c @@ -134,7 +134,7 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, mp_arg_parse_all(n_pos, args, &kw_args, n_allowed, allowed, out_vals); } -#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || _MSC_VER +#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || defined(_MSC_VER) NORETURN void mp_arg_error_terse_mismatch(void) { mp_raise_msg(&mp_type_TypeError, "argument num/types mismatch"); } diff --git a/py/gc.c b/py/gc.c index 7ed53cfc7f..f883a724ef 100644 --- a/py/gc.c +++ b/py/gc.c @@ -392,6 +392,16 @@ void gc_info(gc_info_t *info) { GC_EXIT(); } +void gc_mark_block(void * ptr) { + if (VERIFY_PTR(ptr)) { + size_t _block = BLOCK_FROM_PTR(ptr); + if (ATB_GET_KIND(_block) == AT_HEAD) { + /* an unmarked head, mark it, and push it on gc stack */ + ATB_HEAD_TO_MARK(_block); + } + } +} + void *gc_alloc(size_t n_bytes, bool has_finaliser) { size_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK; DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks); @@ -833,7 +843,10 @@ void gc_dump_alloc_table(void) { */ /* this prints the uPy object type of the head block */ case AT_HEAD: { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" void **ptr = (void**)(MP_STATE_MEM(gc_pool_start) + bl * BYTES_PER_BLOCK); +#pragma GCC diagnostic pop if (*ptr == &mp_type_tuple) { c = 'T'; } else if (*ptr == &mp_type_list) { c = 'L'; } else if (*ptr == &mp_type_dict) { c = 'D'; } diff --git a/py/gc.h b/py/gc.h index 7d8fe2bf8c..64c4789965 100644 --- a/py/gc.h +++ b/py/gc.h @@ -45,6 +45,9 @@ void gc_collect_start(void); void gc_collect_root(void **ptrs, size_t len); void gc_collect_end(void); +// During a collect, use this to mark blocks used in C but allocated using gc_alloc. +void gc_mark_block(void * ptr); + void *gc_alloc(size_t n_bytes, bool has_finaliser); void gc_free(void *ptr); // does not call finaliser size_t gc_nbytes(const void *ptr); diff --git a/py/modbuiltins.c b/py/modbuiltins.c index cbdcc9aae0..401d9f541b 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -470,9 +470,9 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) { mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val); mp_int_t r = rounded; // make rounded value even if it was halfway between ints - if (val - rounded == 0.5) { + if (val - rounded >= 0.5) { r = (r + 1) & (~1); - } else if (val - rounded == -0.5) { + } else if (val - rounded <= -0.5) { r &= ~1; } if (n_args > 1) { diff --git a/py/modmath.c b/py/modmath.c index 7c51eab03a..7b67751bcc 100644 --- a/py/modmath.c +++ b/py/modmath.c @@ -70,7 +70,7 @@ STATIC NORETURN void math_error(void) { } \ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name); -#if MP_NEED_LOG2 +#ifdef MP_NEED_LOG2 // 1.442695040888963407354163704 is 1/_M_LN2 #define log2(x) (log(x) * 1.442695040888963407354163704) #endif diff --git a/py/mpstate.h b/py/mpstate.h index 439ed66066..66504b5276 100644 --- a/py/mpstate.h +++ b/py/mpstate.h @@ -146,12 +146,12 @@ typedef struct _mp_state_vm_t { // root pointers for extmod - #if MICROPY_PY_OS_DUPTERM + #ifdef MICROPY_PY_OS_DUPTERM mp_obj_t term_obj; mp_obj_t dupterm_arr_obj; #endif - #if MICROPY_PY_LWIP_SLIP + #ifdef MICROPY_PY_LWIP_SLIP mp_obj_t lwip_slip_stream; #endif diff --git a/py/nlr.h b/py/nlr.h index 6c86fc26c3..225d200cbf 100644 --- a/py/nlr.h +++ b/py/nlr.h @@ -41,6 +41,7 @@ struct _nlr_buf_t { nlr_buf_t *prev; void *ret_val; // always a concrete object (an exception instance) #if !defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP +#define MICROPY_NLR_SETJMP (0) #if defined(__i386__) void *regs[6]; #elif defined(__x86_64__) diff --git a/py/obj.h b/py/obj.h index 61db65a9a2..1da8f3e5a2 100644 --- a/py/obj.h +++ b/py/obj.h @@ -513,8 +513,6 @@ struct _mp_obj_type_t { extern const mp_obj_type_t mp_type_type; extern const mp_obj_type_t mp_type_object; extern const mp_obj_type_t mp_type_NoneType; -extern const mp_obj_type_t mp_type_bool; -extern const mp_obj_type_t mp_type_int; extern const mp_obj_type_t mp_type_str; extern const mp_obj_type_t mp_type_bytes; extern const mp_obj_type_t mp_type_bytearray; diff --git a/py/objcomplex.c b/py/objcomplex.c index 96be25255c..b302b1d56d 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -39,6 +39,9 @@ #include #include "py/formatfloat.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + typedef struct _mp_obj_complex_t { mp_obj_base_t base; mp_float_t real; @@ -248,4 +251,6 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t return mp_obj_new_complex(lhs_real, lhs_imag); } +#pragma GCC diagnostic pop + #endif diff --git a/py/objfloat.c b/py/objfloat.c index 73d07feac8..4a32a9e965 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -39,6 +39,9 @@ #include #include "py/formatfloat.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" + #if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D // M_E and M_PI are not part of the math.h standard and may not be defined @@ -252,4 +255,6 @@ mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_i return mp_obj_new_float(lhs_val); } +#pragma GCC diagnostic pop + #endif // MICROPY_PY_BUILTINS_FLOAT diff --git a/py/objmodule.c b/py/objmodule.c index 9b06e3b7b5..7ed3175c0d 100644 --- a/py/objmodule.c +++ b/py/objmodule.c @@ -201,13 +201,13 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = { #if MICROPY_PY_USSL { MP_ROM_QSTR(MP_QSTR_ussl), MP_ROM_PTR(&mp_module_ussl) }, #endif -#if MICROPY_PY_LWIP +#ifdef MICROPY_PY_LWIP { MP_ROM_QSTR(MP_QSTR_lwip), MP_ROM_PTR(&mp_module_lwip) }, #endif #if MICROPY_PY_WEBSOCKET { MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&mp_module_websocket) }, #endif -#if MICROPY_PY_WEBREPL +#ifdef MICROPY_PY_WEBREPL { MP_ROM_QSTR(MP_QSTR__webrepl), MP_ROM_PTR(&mp_module_webrepl) }, #endif #if MICROPY_PY_FRAMEBUF diff --git a/py/objproperty.c b/py/objproperty.c index 8189935d20..e7e5cd9861 100644 --- a/py/objproperty.c +++ b/py/objproperty.c @@ -28,15 +28,11 @@ #include #include "py/nlr.h" +#include "py/objproperty.h" #include "py/runtime.h" #if MICROPY_PY_BUILTINS_PROPERTY -typedef struct _mp_obj_property_t { - mp_obj_base_t base; - mp_obj_t proxy[3]; // getter, setter, deleter -} mp_obj_property_t; - STATIC mp_obj_t property_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { enum { ARG_fget, ARG_fset, ARG_fdel, ARG_doc }; static const mp_arg_t allowed_args[] = { diff --git a/py/objproperty.h b/py/objproperty.h new file mode 100644 index 0000000000..1852e6b6e9 --- /dev/null +++ b/py/objproperty.h @@ -0,0 +1,40 @@ +/* + * 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_PY_OBJPROPERTY_H__ +#define __MICROPY_INCLUDED_PY_OBJPROPERTY_H__ + +#include "py/obj.h" + +#if MICROPY_PY_BUILTINS_PROPERTY + +typedef struct _mp_obj_property_t { + mp_obj_base_t base; + mp_obj_t proxy[3]; // getter, setter, deleter +} mp_obj_property_t; + +#endif // MICROPY_PY_BUILTINS_PROPERTY + +#endif // __MICROPY_INCLUDED_PY_OBJPROPERTY_H__ diff --git a/py/objtype.c b/py/objtype.c index 8b46c54001..0fbc597cde 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -110,7 +110,10 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_ // this should not be applied to class types, as will result in extra // lookup either. if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" if (*(void**)((char*)type + lookup->meth_offset) != NULL) { +#pragma GCC diagnostic pop DEBUG_printf("mp_obj_class_lookup: matched special meth slot for %s\n", qstr_str(lookup->attr)); lookup->dest[0] = MP_OBJ_SENTINEL; return; @@ -368,7 +371,7 @@ STATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) { if (member[0] == MP_OBJ_NULL) { // https://docs.python.org/3/reference/datamodel.html#object.__hash__ // "User-defined classes have __eq__() and __hash__() methods by default; - // with them, all objects compare unequal (except with themselves) and + // with them, all objects compare unequal (except with themselves) and // x.__hash__() returns an appropriate value such that x == y implies // both that x is y and hash(x) == hash(y)." return MP_OBJ_NEW_SMALL_INT((mp_uint_t)self_in); diff --git a/py/parse.c b/py/parse.c index 397d46d9f0..1787265b37 100644 --- a/py/parse.c +++ b/py/parse.c @@ -152,6 +152,8 @@ typedef struct _parser_t { #endif } parser_t; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-align" STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) { // use a custom memory allocator to store parse nodes sequentially in large chunks @@ -192,6 +194,7 @@ STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) { chunk->union_.used += num_bytes; return ret; } +#pragma GCC diagnostic pop STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) { if (parser->parse_error) { diff --git a/py/runtime.c b/py/runtime.c index c255574643..f48a527550 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -34,6 +34,7 @@ #include "py/compile.h" #include "py/objstr.h" #include "py/objtuple.h" +#include "py/objtype.h" #include "py/objlist.h" #include "py/objmodule.h" #include "py/objgenerator.h" @@ -102,7 +103,7 @@ void mp_deinit(void) { //mp_obj_dict_free(&dict_main); mp_module_deinit(); - // call port specific deinitialization if any + // call port specific deinitialization if any #ifdef MICROPY_PORT_INIT_FUNC MICROPY_PORT_DEINIT_FUNC; #endif @@ -989,6 +990,22 @@ void mp_convert_member_lookup(mp_obj_t self, const mp_obj_type_t *type, mp_obj_t dest[0] = member; dest[1] = self; } + #if MICROPY_PY_BUILTINS_PROPERTY + } else if (MP_OBJ_IS_TYPE(member, &mp_type_property) && mp_obj_is_native_type(type)) { + // object member is a property; delegate the load to the property + // Note: This is an optimisation for code size and execution time. + // The proper way to do it is have the functionality just below + // in a __get__ method of the property object, and then it would + // be called by the descriptor code down below. But that way + // requires overhead for the nested mp_call's and overhead for + // the code. + const mp_obj_t *proxy = mp_obj_property_get(member); + if (proxy[0] == mp_const_none) { + mp_raise_msg(&mp_type_AttributeError, "unreadable attribute"); + } else { + dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self); + } + #endif } else { // class member is a value, so just return that value dest[0] = member; @@ -1068,6 +1085,35 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { // success return; } + #if MICROPY_PY_BUILTINS_PROPERTY + } else if (type->locals_dict != NULL) { + // generic method lookup + // this is a lookup in the object (ie not class or type) + assert(type->locals_dict->base.type == &mp_type_dict); // Micro Python restriction, for now + mp_map_t *locals_map = &type->locals_dict->map; + mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP); + if (elem != NULL && MP_OBJ_IS_TYPE(elem->value, &mp_type_property)) { + // attribute exists and is a property; delegate the store/delete + // Note: This is an optimisation for code size and execution time. + // The proper way to do it is have the functionality just below in + // a __set__/__delete__ method of the property object, and then it + // would be called by the descriptor code down below. But that way + // requires overhead for the nested mp_call's and overhead for + // the code. + const mp_obj_t *proxy = mp_obj_property_get(elem->value); + mp_obj_t dest[2] = {base, value}; + if (value == MP_OBJ_NULL) { + // delete attribute + if (proxy[2] != mp_const_none) { + mp_call_function_n_kw(proxy[2], 1, 0, dest); + return; + } + } else if (proxy[1] != mp_const_none) { + mp_call_function_n_kw(proxy[1], 2, 0, dest); + return; + } + } + #endif } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_raise_msg(&mp_type_AttributeError, "no such attribute"); diff --git a/py/runtime0.h b/py/runtime0.h index 8d62403a7c..a803c3665f 100644 --- a/py/runtime0.h +++ b/py/runtime0.h @@ -26,6 +26,8 @@ #ifndef __MICROPY_INCLUDED_PY_RUNTIME0_H__ #define __MICROPY_INCLUDED_PY_RUNTIME0_H__ +#include "mpconfig.h" + // These must fit in 8 bits; see scope.h #define MP_SCOPE_FLAG_VARARGS (0x01) #define MP_SCOPE_FLAG_VARKEYWORDS (0x02) diff --git a/shared-bindings/bitbangio/I2C.c b/shared-bindings/bitbangio/I2C.c new file mode 100644 index 0000000000..d92b0db821 --- /dev/null +++ b/shared-bindings/bitbangio/I2C.c @@ -0,0 +1,181 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// This file contains all of the Python API definitions for the +// bitbangio.I2C class. + +#include "shared-bindings/bitbangio/I2C.h" + +#include "py/runtime.h" +//| .. currentmodule:: bitbangio +//| +//| :class:`I2C` --- Two wire serial protocol +//| ------------------------------------------ +//| +//| .. class:: I2C(scl, sda, \*, freq=400000) +//| +//| I2C is a two-wire protocol for communicating between devices. At the +//| physical level it consists of 2 wires: SCL and SDA, the clock and data +//| lines respectively. +//| +//| :param ~microcontroller.Pin scl: The clock pin +//| :param ~microcontroller.Pin sda: The data pin +//| :param int freq: The clock frequency +//| +STATIC mp_obj_t bitbangio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + bitbangio_i2c_obj_t *self = m_new_obj(bitbangio_i2c_obj_t); + self->base.type = &bitbangio_i2c_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_scl, ARG_sda, ARG_freq }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + }; + 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); + const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj); + const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); + shared_module_bitbangio_i2c_construct(self, scl, sda, args[ARG_freq].u_int); + return (mp_obj_t)self; +} + +//| .. method:: I2C.deinit() +//| +//| Releases control of the underlying hardware so other classes can use it. +//| +STATIC mp_obj_t bitbangio_i2c_obj_deinit(mp_obj_t self_in) { + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + shared_module_bitbangio_i2c_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_deinit_obj, bitbangio_i2c_obj_deinit); + +//| .. method:: I2C.__enter__() +//| +//| No-op used in Context Managers. +//| +STATIC mp_obj_t bitbangio_i2c_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c___enter___obj, bitbangio_i2c_obj___enter__); + +//| .. method:: I2C.__exit__() +//| +//| Automatically deinitializes the hardware on context exit. +//| +STATIC mp_obj_t bitbangio_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + shared_module_bitbangio_i2c_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_i2c_obj___exit___obj, 4, 4, bitbangio_i2c_obj___exit__); + +//| .. method:: I2C.scan() +//| +//| Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of +//| those that respond. A device responds if it pulls the SDA line low after +//| its address (including a read bit) is sent on the bus. +//| +STATIC mp_obj_t bitbangio_i2c_scan(mp_obj_t self_in) { + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t list = mp_obj_new_list(0, NULL); + // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved + for (int addr = 0x08; addr < 0x78; ++addr) { + bool success = shared_module_bitbangio_i2c_probe(self, addr); + if (success) { + mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); + } + } + return list; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_scan_obj, bitbangio_i2c_scan); + +//| .. method:: I2C.writeto(address, buffer, stop=True) +//| +//| Write the bytes from ``buffer`` to the slave specified by ``address``. +//| Transmits a stop bit if ``stop`` is set. +//| +STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_address, ARG_buffer, ARG_stop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_stop, MP_ARG_BOOL, {.u_bool = true} }, + }; + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // get the buffer to write the data from + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); + + // do the transfer + bool ok = shared_module_bitbangio_i2c_write(self, args[ARG_address].u_int, + bufinfo.buf, bufinfo.len, args[ARG_stop].u_bool); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_writeto); + +//| .. method:: I2C.readfrom_into(address, buffer) +//| +//| Read into ``buffer`` from the slave specified by ``address``. +//| The number of bytes read will be the length of `buf`. +//| +STATIC mp_obj_t bitbangio_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { + bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); + shared_module_bitbangio_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_3(bitbangio_i2c_readfrom_into_obj, bitbangio_i2c_readfrom_into); + +STATIC const mp_rom_map_elem_t bitbangio_i2c_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bitbangio_i2c_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&bitbangio_i2c___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&bitbangio_i2c_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&bitbangio_i2c_scan_obj) }, + + // standard bus operations + { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&bitbangio_i2c_writeto_obj) }, + { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&bitbangio_i2c_readfrom_into_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bitbangio_i2c_locals_dict, bitbangio_i2c_locals_dict_table); + +const mp_obj_type_t bitbangio_i2c_type = { + { &mp_type_type }, + .name = MP_QSTR_I2C, + .make_new = bitbangio_i2c_make_new, + .locals_dict = (mp_obj_dict_t*)&bitbangio_i2c_locals_dict, +}; diff --git a/shared-bindings/bitbangio/I2C.h b/shared-bindings/bitbangio/I2C.h new file mode 100644 index 0000000000..71d379eb8d --- /dev/null +++ b/shared-bindings/bitbangio/I2C.h @@ -0,0 +1,59 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_SHARED_BINDINGS_BITBANGIO_I2C_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO_I2C_H__ + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "shared-module/bitbangio/types.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t bitbangio_i2c_type; + +// Initializes the hardware peripheral. +extern void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self, + const mcu_pin_obj_t * scl, + const mcu_pin_obj_t * sda, + uint32_t freq); + +extern void shared_module_bitbangio_i2c_deinit(bitbangio_i2c_obj_t *self); + +// Probe the bus to see if a device acknowledges the given address. +extern bool shared_module_bitbangio_i2c_probe(bitbangio_i2c_obj_t *self, uint8_t addr); + +extern bool shared_module_bitbangio_i2c_write(bitbangio_i2c_obj_t *self, + uint16_t address, + const uint8_t * data, size_t len, + bool stop); + +// Reads memory of the i2c device picking up where it left off. +extern bool shared_module_bitbangio_i2c_read(bitbangio_i2c_obj_t *self, + uint16_t address, + uint8_t * data, size_t len); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO_I2C_H__ diff --git a/shared-bindings/bitbangio/SPI.c b/shared-bindings/bitbangio/SPI.c new file mode 100644 index 0000000000..560834ac8a --- /dev/null +++ b/shared-bindings/bitbangio/SPI.c @@ -0,0 +1,178 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// This file contains all of the Python API definitions for the +// bitbangio.SPI class. + +#include + +#include "shared-bindings/bitbangio/SPI.h" + +#include "py/runtime.h" + +//| .. currentmodule:: bitbangio +//| +//| :class:`SPI` -- a 3-4 wire serial protocol +//| ----------------------------------------------- +//| +//| SPI is a serial protocol that has exclusive pins for data in and out of the +//| master. It is typically faster than :py:class:`~bitbangio.I2C` because a +//| separate pin is used to control the active slave rather than a transmitted +//| address. This class only manages three of the four SPI lines: `!clock`, +//| `!MOSI`, `!MISO`. Its up to the client to manage the appropriate slave +//| select line. (This is common because multiple slaves can share the `!clock`, +//| `!MOSI` and `!MISO` lines and therefore the hardware.) +//| +//| .. class:: SPI(clock, MOSI, MISO, baudrate=1000000) +//| +//| Construct an SPI object on the given pins. +//| +//| :param ~microcontroller.Pin clock: the pin to use for the clock. +//| :param ~microcontroller.Pin MOSI: the Master Out Slave In pin. +//| :param ~microcontroller.Pin MISO: the Master In Slave Out pin. +//| :param int baudrate: is the SCK clock rate. +//| + +// TODO(tannewt): Support LSB SPI. +// TODO(tannewt): Support phase, polarity and bit order. +STATIC mp_obj_t bitbangio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + bitbangio_spi_obj_t *self = m_new_obj(bitbangio_spi_obj_t); + self->base.type = &bitbangio_spi_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MOSI, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MISO, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, + { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + }; + 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); + const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(args[ARG_clock].u_obj); + const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj); + const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(args[ARG_MISO].u_obj); + shared_module_bitbangio_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int); + return (mp_obj_t)self; +} + +//| .. method:: SPI.deinit() +//| +//| Turn off the SPI bus. +//| +STATIC mp_obj_t bitbangio_spi_obj_deinit(mp_obj_t self_in) { + bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + shared_module_bitbangio_spi_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi_deinit_obj, bitbangio_spi_obj_deinit); + +//| .. method:: SPI.__enter__() +//| +//| No-op used by Context Managers. +//| +STATIC mp_obj_t bitbangio_spi_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_spi___enter___obj, bitbangio_spi_obj___enter__); + +//| .. method:: SPI.__exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. +//| +STATIC mp_obj_t bitbangio_spi_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + shared_module_bitbangio_spi_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bitbangio_spi_obj___exit___obj, 4, 4, bitbangio_spi_obj___exit__); + +//| .. method:: SPI.transfer(write_buffer=None, read_buffer=None, address=0) +//| +//| Write out ``write_buffer`` and then read into ``read_buffer``. They do +//| not need to be the same length. If either buffer is omitted then the +//| transfer skips the corresponding portion. +//| +//| ``address`` is taken for I2C compatibility but is ignored. +//| +//| When writing, data received is dropped. When reading, zeroes are written +//| out. +//| +STATIC mp_obj_t bitbangio_spi_transfer(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_write_buffer, ARG_read_buffer, ARG_address }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_write_buffer, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL } }, + { MP_QSTR_read_buffer, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL } }, + { MP_QSTR_address, MP_ARG_INT, {.u_int = 0} }, + }; + bitbangio_spi_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // get the buffer to store data into + mp_buffer_info_t write_bufinfo; + if (!mp_get_buffer(args[ARG_write_buffer].u_obj, &write_bufinfo, MP_BUFFER_READ)) { + write_bufinfo.len = 0; + } + + mp_buffer_info_t read_bufinfo; + if (!mp_get_buffer(args[ARG_read_buffer].u_obj, &read_bufinfo, MP_BUFFER_WRITE)) { + read_bufinfo.len = 0; + } + + if (write_bufinfo.len == 0 && read_bufinfo.len == 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "At least one buffer should be provided.")); + } + + // do the transfer + bool ok = shared_module_bitbangio_spi_transfer(self, write_bufinfo.buf, + write_bufinfo.len, read_bufinfo.buf, read_bufinfo.len); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_spi_transfer_obj, 2, bitbangio_spi_transfer); + +STATIC const mp_rom_map_elem_t bitbangio_spi_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bitbangio_spi_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&bitbangio_spi___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&bitbangio_spi_obj___exit___obj) }, + + { MP_ROM_QSTR(MP_QSTR_transfer), MP_ROM_PTR(&bitbangio_spi_transfer_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(bitbangio_spi_locals_dict, bitbangio_spi_locals_dict_table); + +const mp_obj_type_t bitbangio_spi_type = { + { &mp_type_type }, + .name = MP_QSTR_SPI, + .make_new = bitbangio_spi_make_new, + .locals_dict = (mp_obj_dict_t*)&bitbangio_spi_locals_dict, +}; diff --git a/shared-bindings/bitbangio/SPI.h b/shared-bindings/bitbangio/SPI.h new file mode 100644 index 0000000000..a11df1f7b6 --- /dev/null +++ b/shared-bindings/bitbangio/SPI.h @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_SHARED_BINDINGS_BITBANGIO_SPI_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO_SPI_H__ + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "shared-module/bitbangio/types.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t bitbangio_spi_type; + +// Construct an underlying SPI object. +extern void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, + const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, + const mcu_pin_obj_t * miso, uint32_t baudrate); + +extern void shared_module_bitbangio_spi_deinit(bitbangio_spi_obj_t *self); + +// Write out write_buffer then read read_buffer. Returns true on success, false +// otherwise. +extern bool shared_module_bitbangio_spi_transfer(bitbangio_spi_obj_t *self, + const uint8_t *write_buffer, size_t write_buffer_len, + uint8_t *read_buffer, size_t read_buffer_len); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO_SPI_H__ diff --git a/shared-bindings/bitbangio/__init__.c b/shared-bindings/bitbangio/__init__.c new file mode 100644 index 0000000000..69e39a2e52 --- /dev/null +++ b/shared-bindings/bitbangio/__init__.c @@ -0,0 +1,93 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// bitbangio implements some standard protocols in the processor. Its only +// dependency is nativeio.DigitalInOut. + +#include +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/bitbangio/__init__.h" +#include "shared-bindings/bitbangio/I2C.h" +#include "shared-bindings/bitbangio/SPI.h" +#include "shared-module/bitbangio/types.h" + +#include "py/runtime.h" + +//| :mod:`bitbangio` --- Digital protocols implemented by the CPU +//| ============================================================= +//| +//| .. module:: bitbangio +//| :synopsis: Digital protocols implemented by the CPU +//| :platform: SAMD21 +//| +//| The `bitbangio` module contains classes to provide digital protocol support +//| regardless of whether the underlying hardware exists to use the protocol. +//| +//| First try to use `nativeio` module instead which utilizes peripheral +//| hardware to implement the protocols. Native implementations will be faster +//| than bitbanged versions and have more capabilities. +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| I2C +//| SPI +//| +//| All libraries change hardware state and should be deinitialized when they +//| are no longer needed. To do so, either call :py:meth:`!deinit` or use a +//| context manager. +//| +//| For example:: +//| +//| import bitbangio +//| from board import * +//| +//| with bitbangio.I2C(SCL, SDA) as i2c: +//| i2c.scan() +//| +//| This example will initialize the the device, run +//| :py:meth:`~bitbangio.I2C.scan` and then :py:meth:`~bitbangio.I2C.deinit` the +//| hardware. +//| + +STATIC const mp_rom_map_elem_t bitbangio_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bitbangio) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&bitbangio_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&bitbangio_spi_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bitbangio_module_globals, bitbangio_module_globals_table); + +const mp_obj_module_t bitbangio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&bitbangio_module_globals, +}; diff --git a/shared-bindings/bitbangio/__init__.h b/shared-bindings/bitbangio/__init__.h new file mode 100644 index 0000000000..4404501eb0 --- /dev/null +++ b/shared-bindings/bitbangio/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_SHARED_BINDINGS_BITBANGIO___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO___INIT___H__ + +#include "py/obj.h" + +// Nothing now. + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_BITBANGIO___INIT___H__ diff --git a/atmel-samd/modmachine.c b/shared-bindings/board/__init__.c similarity index 51% rename from atmel-samd/modmachine.c rename to shared-bindings/board/__init__.c index 791e09ada6..06c2f218fb 100644 --- a/atmel-samd/modmachine.c +++ b/shared-bindings/board/__init__.c @@ -3,8 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013-2015 Damien P. George - * Copyright (c) 2016 Paul Sokolovsky + * Copyright (c) 2016 Scott Shawcroft * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,37 +24,21 @@ * THE SOFTWARE. */ -#include -#include - #include "py/obj.h" -#include "py/runtime.h" -#include "shared-bindings/modules/machine.h" +#include "shared-bindings/board/__init__.h" -#include "modmachine_adc.h" -#include "modmachine_dac.h" -#include "modmachine_pin.h" -#include "modmachine_pwm.h" +//| :mod:`board` --- Board specific pin names +//| ======================================================== +//| +//| .. module:: board +//| :synopsis: Board specific pin names +//| :platform: SAMD21 +//| +//| Common container for board base pin names. These will vary from board to +//| board so don't expect portability when using this module. -#if MICROPY_PY_MACHINE -// TODO(tannewt): Add the machine_ prefix to all types so that we don't risk -// conflicting with any port specific implementations. -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_ADC), MP_ROM_PTR(&adc_type) }, - { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&dac_type) }, - { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, - { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) }, - { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pwm_type) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, -}; - -STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); - -const mp_obj_module_t machine_module = { +const mp_obj_module_t board_module = { .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&machine_module_globals, + .globals = (mp_obj_dict_t*)&board_module_globals, }; - -#endif // MICROPY_PY_MACHINE diff --git a/shared-bindings/board/__init__.h b/shared-bindings/board/__init__.h new file mode 100644 index 0000000000..9ab646a453 --- /dev/null +++ b/shared-bindings/board/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_SHARED_BINDINGS_BOARD___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_BOARD___INIT___H__ + +#include "py/obj.h" + +extern const mp_obj_dict_t board_module_globals; + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_BOARD___INIT___H__ diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst index 42394febeb..c1c63276ce 100644 --- a/shared-bindings/index.rst +++ b/shared-bindings/index.rst @@ -9,4 +9,4 @@ follow. :glob: :maxdepth: 3 - modules/* + */__init__ diff --git a/shared-bindings/microcontroller/Pin.c b/shared-bindings/microcontroller/Pin.c new file mode 100644 index 0000000000..733fa29ec9 --- /dev/null +++ b/shared-bindings/microcontroller/Pin.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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 "shared-bindings/microcontroller/Pin.h" + +//| .. currentmodule:: microcontroller +//| +//| :class:`Pin` --- Pin reference +//| ------------------------------------------ +//| +//| Identifies an IO pin on the microcontroller. +//| +//| .. class:: Pin +//| +//| Identifies an IO pin on the microcontroller. They are fixed by the +//| hardware so they cannot be constructed on demand. Instead, use +//| `board` or `microcontroller.pin` to reference the desired pin. +//| + +const mp_obj_type_t mcu_pin_type = { + { &mp_type_type }, + .name = MP_QSTR_Pin, +}; diff --git a/shared-bindings/microcontroller/Pin.h b/shared-bindings/microcontroller/Pin.h new file mode 100644 index 0000000000..96df67ef86 --- /dev/null +++ b/shared-bindings/microcontroller/Pin.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_SHARED_BINDINGS_MICROCONTROLLER_PIN_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PIN_H__ + +#include "py/obj.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t mcu_pin_type; + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER_PIN_H__ diff --git a/shared-bindings/microcontroller/__init__.c b/shared-bindings/microcontroller/__init__.c new file mode 100644 index 0000000000..2392518056 --- /dev/null +++ b/shared-bindings/microcontroller/__init__.c @@ -0,0 +1,99 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// Microcontroller contains pin references and microcontroller specific control +// functions. + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "common-hal/microcontroller/types.h" + +#include "py/runtime.h" + +//| :mod:`microcontroller` --- Pin references and core functionality +//| ================================================================ +//| +//| .. module:: microcontroller +//| :synopsis: Pin references and core functionality +//| :platform: SAMD21 +//| +//| The `microcontroller` module defines the pins from the perspective of the +//| microcontroller. See `board` for board-specific pin mappings. +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| Pin +//| + +//| .. method:: delay_us(delay) +//| +//| Dedicated delay method used for very short delays. DO NOT do long delays +//| because it will stall any concurrent code. +//| +STATIC mp_obj_t mcu_delay_us(mp_obj_t delay_obj) { + uint32_t delay = mp_obj_get_int(delay_obj); + + common_hal_mcu_delay_us(delay); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mcu_delay_us_obj, mcu_delay_us); + +//| :mod:`microcontroller.pin` --- Microcontroller pin names +//| -------------------------------------------------------- +//| +//| .. module:: microcontroller.pin +//| :synopsis: Microcontroller pin names +//| :platform: SAMD21 +//| +//| References to pins as named by the microcontroller +//| +const mp_obj_module_t mcu_pin_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mcu_pin_globals, +}; + +STATIC const mp_rom_map_elem_t mcu_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_microcontroller) }, + { MP_ROM_QSTR(MP_QSTR_delay_us), MP_ROM_PTR(&mcu_delay_us_obj) }, + { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&mcu_pin_type) }, + { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&mcu_pin_module) }, +}; + +STATIC MP_DEFINE_CONST_DICT(mcu_module_globals, mcu_module_globals_table); + +const mp_obj_module_t microcontroller_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&mcu_module_globals, +}; diff --git a/shared-bindings/microcontroller/__init__.h b/shared-bindings/microcontroller/__init__.h new file mode 100644 index 0000000000..3600d3b083 --- /dev/null +++ b/shared-bindings/microcontroller/__init__.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_SHARED_BINDINGS_MICROCONTROLLER___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER___INIT___H__ + +#include "py/obj.h" + +extern void common_hal_mcu_delay_us(uint32_t); + +extern const mp_obj_dict_t mcu_pin_globals; + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_MICROCONTROLLER___INIT___H__ diff --git a/shared-bindings/modules/machine.c b/shared-bindings/modules/machine.c deleted file mode 100644 index 49c8b00aa7..0000000000 --- a/shared-bindings/modules/machine.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Scott Shawcroft - * - * 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. - */ - -// This file contains all of the Python API definitions for the machine module. -// Machine is the HAL for low-level, hardware accelerated functions. It is not -// meant to simplify APIs, its only meant to unify them so that other modules -// do not require port specific logic. - -#include "machine.h" - -#include "py/runtime.h" - -//| :mod:`machine` --- functions related to the board -//| ================================================= -//| -//| .. module:: machine -//| :synopsis: functions related to the board -//| :platform: SAMD21 -//| -//| The ``machine`` module contains specific functions related to the board. -//| -//| This is soon to be renamed to distinguish it from upstream's `machine`! -//| -//| :class:`I2C` --- Two wire serial protocol -//| ------------------------------------------ -//| -//| .. class:: I2C(scl, sda, \*, freq=400000) -//| -//| I2C is a two-wire protocol for communicating between devices. At the -//| physical level it consists of 2 wires: SCL and SDA, the clock and data lines -//| respectively. -//| -//| I2C objects are created attached to a specific bus. They can be initialised -//| when created, or initialised later on. -//| -//| :param str scl: The clock pin -//| :param str sda: The data pin -//| :param int freq: The clock frequency -//| -STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); - machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t); - self->base.type = &machine_i2c_type; - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_scl, ARG_sda, ARG_freq }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - }; - 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); - // TODO(tannewt): Replace pin_find with a unified version. - const pin_obj_t* scl = pin_find(args[ARG_scl].u_obj); - const pin_obj_t* sda = pin_find(args[ARG_sda].u_obj); - mp_hal_i2c_construct(self, scl, sda, args[ARG_freq].u_int); - return (mp_obj_t)self; -} - - -//| .. method:: I2C.deinit() -//| -//| Releases control of the underlying hardware so other classes can use it. -//| -STATIC mp_obj_t machine_i2c_obj_deinit(mp_obj_t self_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_hal_i2c_deinit(self); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_deinit_obj, machine_i2c_obj_deinit); - -//| .. method:: I2C.__enter__() -//| -//| No-op used in Context Managers. -//| -STATIC mp_obj_t machine_i2c_obj___enter__(mp_obj_t self_in) { - return self_in; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c___enter___obj, machine_i2c_obj___enter__); - -//| .. method:: I2C.__exit__() -//| -//| Automatically deinitializes the hardware on context exit. -//| -STATIC mp_obj_t machine_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - mp_hal_i2c_deinit(args[0]); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_obj___exit___obj, 4, 4, machine_i2c_obj___exit__); - -//| .. method:: I2C.scan() -//| -//| Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of -//| those that respond. A device responds if it pulls the SDA line low after -//| its address (including a read bit) is sent on the bus. -//| -STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_t list = mp_obj_new_list(0, NULL); - // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved - for (int addr = 0x08; addr < 0x78; ++addr) { - bool success = mp_hal_i2c_probe(self, addr); - if (success) { - mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); - } - } - return list; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan); - -//| .. method:: I2C.readfrom(addr, nbytes) -//| -//| Read `nbytes` from the slave specified by `addr`. -//| -//| :param int addr: The 7 bit address of the device -//| :param int nbytes: The number of bytes to read -//| :return: the data read -//| :rtype: bytes -//| -STATIC mp_obj_t machine_i2c_readfrom(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t nbytes_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - vstr_t vstr; - vstr_init_len(&vstr, mp_obj_get_int(nbytes_in)); - mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)vstr.buf, vstr.len); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); -} -MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_obj, machine_i2c_readfrom); - -//| .. method:: I2C.readfrom_into(addr, buf) -//| -//| Read into `buf` from the slave specified by `addr`. -//| The number of bytes read will be the length of `buf`. -//| -STATIC mp_obj_t machine_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); - mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)bufinfo.buf, bufinfo.len); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_into_obj, machine_i2c_readfrom_into); - -//| .. method:: I2C.writeto(addr, buf) -//| -//| Write the bytes from `buf` to the slave specified by `addr`. -//| -STATIC mp_obj_t machine_i2c_writeto(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); - mp_hal_i2c_write(self, mp_obj_get_int(addr_in), bufinfo.buf, bufinfo.len); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_writeto_obj, machine_i2c_writeto); - -//| .. method:: I2C.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8) -//| -//| Read `nbytes` from the slave specified by `addr` starting from the memory -//| address specified by `memaddr`. -//| The argument `addrsize` specifies the address size in bits (on ESP8266 -//| this argument is not recognised and the address size is always 8 bits). -//| Returns a `bytes` object with the data read. -//| -STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO - }; - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // create the buffer to store data into - vstr_t vstr; - vstr_init_len(&vstr, args[ARG_n].u_int); - - // do the transfer - mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, (uint8_t*)vstr.buf, vstr.len); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem); - - -//| .. method:: I2C.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8) -//| -//| Read into `buf` from the slave specified by `addr` starting from the -//| memory address specified by `memaddr`. The number of bytes read is the -//| length of `buf`. -//| The argument `addrsize` specifies the address size in bits (on ESP8266 -//| this argument is not recognised and the address size is always 8 bits). -//| -STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO - }; - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // get the buffer to store data into - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE); - - // do the transfer - mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into); - -//| .. method:: I2C.writeto_mem(addr, memaddr, buf, \*, addrsize=8) -//| -//| Write `buf` to the slave specified by `addr` starting from the -//| memory address specified by `memaddr`. -//| The argument `addrsize` specifies the address size in bits (on ESP8266 -//| this argument is not recognised and the address size is always 8 bits). -//| -STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, - //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO - }; - machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - // get the buffer to write the data from - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); - - // do the transfer - mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem); - -STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_i2c_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&machine_i2c___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&machine_i2c_obj___exit___obj) }, - { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) }, - - // standard bus operations - { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) }, - { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) }, - - // memory operations - // TODO(tannewt): Move these into a separate loadable Python module. - { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) }, - { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(machine_i2c_locals_dict, machine_i2c_locals_dict_table); - -const mp_obj_type_t machine_i2c_type = { - { &mp_type_type }, - .name = MP_QSTR_I2C, - .make_new = machine_i2c_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_i2c_locals_dict, -}; - -//| :class:`SPI` -- a 3-4 wire serial protocol -//| ----------------------------------------------- -//| -//| SPI is a serial protocol that has exlusive pins for data in and out of the -//| master. It is typically faster than `I2C` because a separate pin is used to -//| control the active slave rather than a transitted address. This class only -//| manages three of the four SPI lines: `clock`, `MOSI`, `MISO`. Its up to the -//| client to manage the appropriate slave select line. (This is common because -//| multiple slaves can share the `clock`, `MOSI` and `MISO` lines and therefore -//| the hardware.) -//| -//| .. class:: SPI(clock, MOSI, MISO, baudrate=1000000) -//| -//| Construct an SPI object on the given bus. ``id`` can be only 0. -//| With no additional parameters, the SPI object is created but not -//| initialised (it has the settings from the last initialisation of -//| the bus, if any). If extra arguments are given, the bus is initialised. -//| See ``init`` for parameters of initialisation. -//| -//| - ``clock`` is the pin to use for the clock. -//| - ``MOSI`` is the Master Out Slave In pin. -//| - ``MISO`` is the Master In Slave Out pin. -//| - ``baudrate`` is the SCK clock rate. -//| - -// TODO(tannewt): Support LSB SPI. -// TODO(tannewt): Support phase, polarity and bit order. -STATIC mp_obj_t machine_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); - machine_spi_obj_t *self = m_new_obj(machine_spi_obj_t); - self->base.type = &machine_spi_type; - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; - static const mp_arg_t allowed_args[] = { - { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_MOSI, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_MISO, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, - { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, - { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, - }; - 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); - // TODO(tannewt): Replace pin_find with a unified version. - const pin_obj_t* clock = pin_find(args[ARG_clock].u_obj); - const pin_obj_t* mosi = pin_find(args[ARG_MOSI].u_obj); - const pin_obj_t* miso = pin_find(args[ARG_MISO].u_obj); - mp_hal_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int); - return (mp_obj_t)self; -} - -//| .. method:: SPI.deinit() -//| -//| Turn off the SPI bus. -//| -STATIC mp_obj_t machine_spi_obj_deinit(mp_obj_t self_in) { - machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_hal_spi_deinit(self); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_spi_deinit_obj, machine_spi_obj_deinit); - -//| .. method:: SPI.__enter__() -//| -//| No-op used by Context Managers. -//| -STATIC mp_obj_t machine_spi_obj___enter__(mp_obj_t self_in) { - return self_in; -} -MP_DEFINE_CONST_FUN_OBJ_1(machine_spi___enter___obj, machine_spi_obj___enter__); - -//| .. method:: SPI.__enter__() -//| -//| Automatically deinitializes the hardware when exiting a context. -//| -STATIC mp_obj_t machine_spi_obj___exit__(size_t n_args, const mp_obj_t *args) { - (void)n_args; - mp_hal_spi_deinit(args[0]); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_spi_obj___exit___obj, 4, 4, machine_spi_obj___exit__); - -//| .. method:: SPI.write_readinto(write_buf, read_buf) -//| -//| Write from ``write_buf`` and read into ``read_buf``. Both buffers must have the -//| same length. This is the same as a SPI transfer function on other platforms. -//| Returns the number of bytes written -//| -STATIC mp_obj_t mp_machine_spi_write_readinto(mp_obj_t self_in, mp_obj_t wr_buf, mp_obj_t rd_buf) { - mp_buffer_info_t src; - mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); - mp_buffer_info_t dest; - mp_get_buffer_raise(rd_buf, &dest, MP_BUFFER_WRITE); - if (src.len != dest.len) { - mp_raise_ValueError("buffers must be the same length"); - } - machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_hal_spi_transfer(self, src.len, (uint8_t *) src.buf, (uint8_t *) dest.buf); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_3(mp_machine_spi_write_readinto_obj, mp_machine_spi_write_readinto); - -//| .. method:: SPI.write(buf) -//| -//| Write the data contained in ``buf``. -//| Returns the number of bytes written. -//| -STATIC mp_obj_t mp_machine_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) { - mp_buffer_info_t src; - mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); - machine_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_hal_spi_transfer(self, src.len, (uint8_t *) src.buf, NULL); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_2(mp_machine_spi_write_obj, mp_machine_spi_write); - -//| .. method:: SPI.read(nbytes, *, write=0x00) -//| -//| Read the ``nbytes`` while writing the data specified by ``write``. -//| Return the number of bytes read. -//| -STATIC mp_obj_t mp_machine_spi_read(size_t n_args, const mp_obj_t *args) { - vstr_t vstr; - vstr_init_len(&vstr, mp_obj_get_int(args[1])); - memset(vstr.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, vstr.len); - mp_hal_spi_transfer(args[0], vstr.len, (uint8_t *) vstr.buf, (uint8_t *) vstr.buf); - return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_read_obj, 2, 3, mp_machine_spi_read); - -//| .. method:: SPI.readinto(buf, *, write=0x00) -//| -//| Read into the buffer specified by ``buf`` while writing the data -//| specified by ``write``. -//| Return the number of bytes read. -//| -STATIC mp_obj_t mp_machine_spi_readinto(size_t n_args, const mp_obj_t *args) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); - memset(bufinfo.buf, n_args == 3 ? mp_obj_get_int(args[2]) : 0, bufinfo.len); - mp_hal_spi_transfer(args[0], bufinfo.len, (uint8_t *) bufinfo.buf, (uint8_t *) bufinfo.buf); - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_machine_spi_readinto_obj, 2, 3, mp_machine_spi_readinto); - -STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_spi_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&machine_spi___enter___obj) }, - { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&machine_spi_obj___exit___obj) }, - - // Standard simultaneous read/write transfer. - { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) }, - - // Helper methods. - // TODO(tannewt): Move these into a helper Python class. - { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) }, - { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) }, - { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(machine_spi_locals_dict, machine_spi_locals_dict_table); - -const mp_obj_type_t machine_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .make_new = machine_spi_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_spi_locals_dict, -}; diff --git a/shared-bindings/modules/machine.h b/shared-bindings/modules/machine.h deleted file mode 100644 index a3f8a4a0c8..0000000000 --- a/shared-bindings/modules/machine.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Scott Shawcroft - * - * 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. - */ - -// Machine is the HAL for low-level, hardware accelerated functions. It is not -// meant to simplify APIs, its only meant to unify them so that other modules -// do not require port specific logic. -// -// This file includes externs for all functions a port should implement to -// support the machine module. - -#ifndef __MICROPY_INCLUDED_API_MACHINE_H__ -#define __MICROPY_INCLUDED_API_MACHINE_H__ - -#include "py/obj.h" - -// Should include these structs which will be passed through to the port -// implementation: -// * pin_obj_t -// * machine_i2c_obj_t - -// TODO(tannewt): Standardize the type names. - -#include "machine_types.h" - -#include "modmachine_pin.h" - -// Type object used in Python. Should be shared between ports. -extern const mp_obj_type_t machine_i2c_type; -extern const mp_obj_type_t machine_spi_type; - -// Initializes the hardware peripheral. -extern void mp_hal_i2c_construct(machine_i2c_obj_t *self, const pin_obj_t * scl, - const pin_obj_t * sda, uint32_t freq); - -extern void mp_hal_i2c_init(machine_i2c_obj_t *self); -extern void mp_hal_i2c_deinit(machine_i2c_obj_t *self); - -// Probe the bus to see if a device acknowledges the given address. -extern bool mp_hal_i2c_probe(machine_i2c_obj_t *self, uint8_t addr); - -// Reads memory of the i2c device picking up where it left off. -extern void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, - uint8_t *data, size_t len); - -// Reads memory of the i2c device starting at memaddr. -extern void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr, - uint16_t memaddr, uint8_t *dest, size_t len); - -extern void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, - uint8_t *data, size_t len); - -// Writes memory of the i2c device starting at memaddr. -extern void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr, - uint16_t memaddr, const uint8_t *src, - size_t len); - -// Construct an underlying SPI object. -extern void mp_hal_spi_construct(machine_spi_obj_t *self, const pin_obj_t * clock, - const pin_obj_t * mosi, const pin_obj_t * miso, - uint32_t baudrate); - -extern void mp_hal_spi_init(machine_spi_obj_t *self); -extern void mp_hal_spi_deinit(machine_spi_obj_t *self); - -// Concurrently write and read len bytes from the SPI port. Chip select is -// handled externally. -extern void mp_hal_spi_transfer(machine_spi_obj_t *self, size_t len, const uint8_t *src, uint8_t *dest); - -#endif // __MICROPY_INCLUDED_API_MACHINE_H__ diff --git a/shared-bindings/nativeio/AnalogIn.c b/shared-bindings/nativeio/AnalogIn.c new file mode 100644 index 0000000000..9c5a601da2 --- /dev/null +++ b/shared-bindings/nativeio/AnalogIn.c @@ -0,0 +1,106 @@ +/* + * 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 + +#include "py/binary.h" +#include "py/mphal.h" +#include "py/nlr.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/nativeio/AnalogIn.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`AnalogIn` -- read analog voltage +//| ============================================ +//| +//| Usage:: +//| +//| import nativeio +//| from board import * +//| +//| with nativeio.AnalogIn(A1) as adc: +//| val = adc.value +//| + +//| .. class:: AnalogIn(pin) +//| +//| Use the AnalogIn on the given pin. +//| +//| :param ~microcontroller.Pin pin: the pin to read from +//| +STATIC mp_obj_t nativeio_analogin_make_new(const mp_obj_type_t *type, + mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + // check number of arguments + mp_arg_check_num(n_args, n_kw, 1, 1, false); + + // 1st argument is the pin + mp_obj_t pin_obj = args[0]; + + nativeio_analogin_obj_t *self = m_new_obj(nativeio_analogin_obj_t); + self->base.type = &nativeio_analogin_type; + const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj); + common_hal_nativeio_analogin_construct(self, pin); + + return (mp_obj_t) self; +} + +//| .. attribute:: value +//| +//| Read the value on the analog pin and return it. The returned value +//| will be between 0 and 65535 inclusive (16-bit). Even if the underlying +//| analog to digital converter (ADC) is lower resolution, the result will +//| be scaled to be 16-bit. +//| +//| :return: the data read +//| :rtype: int +//| +STATIC mp_obj_t nativeio_analogin_obj_get_value(mp_obj_t self_in) { + nativeio_analogin_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_nativeio_analogin_get_value(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_analogin_get_value_obj, nativeio_analogin_obj_get_value); + +mp_obj_property_t nativeio_analogin_value_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_analogin_get_value_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t nativeio_analogin_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_value), MP_ROM_PTR(&nativeio_analogin_value_obj)}, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_analogin_locals_dict, nativeio_analogin_locals_dict_table); + +const mp_obj_type_t nativeio_analogin_type = { + { &mp_type_type }, + .name = MP_QSTR_AnalogIn, + .make_new = nativeio_analogin_make_new, + .locals_dict = (mp_obj_t)&nativeio_analogin_locals_dict, +}; diff --git a/shared-bindings/nativeio/AnalogIn.h b/shared-bindings/nativeio/AnalogIn.h new file mode 100644 index 0000000000..e901aa3b7f --- /dev/null +++ b/shared-bindings/nativeio/AnalogIn.h @@ -0,0 +1,38 @@ +/* + * 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_SHARED_BINDINGS_NATIVEIO_ANALOGIN_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGIN_H__ + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +extern const mp_obj_type_t nativeio_analogin_type; + +void common_hal_nativeio_analogin_construct(nativeio_analogin_obj_t* self, const mcu_pin_obj_t *pin); +uint16_t common_hal_nativeio_analogin_get_value(nativeio_analogin_obj_t *self); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGIN_H__ diff --git a/shared-bindings/nativeio/AnalogOut.c b/shared-bindings/nativeio/AnalogOut.c new file mode 100644 index 0000000000..7de336a6a3 --- /dev/null +++ b/shared-bindings/nativeio/AnalogOut.c @@ -0,0 +1,121 @@ +/* + * 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 +#include + +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/nativeio/AnalogOut.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`AnalogOut` -- output analog voltage +//| ============================================ +//| +//| The AnalogOut is used to output analog values (a specific voltage). +//| +//| Example usage:: +//| +//| import nativeio +//| from microcontroller import pin +//| +//| with nativeio.AnalogOut(pin.PA02) as dac: # output on pin PA02 +//| dac.value = 32768 # makes PA02 1.65V +//| + +//| .. class:: AnalogOut(pin) +//| +//| Use the AnalogOut on the given pin. +//| +//| :param ~microcontroller.Pin pin: the pin to output to +//| +STATIC mp_obj_t nativeio_analogout_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + + nativeio_analogout_obj_t *self = m_new_obj(nativeio_analogout_obj_t); + self->base.type = &nativeio_analogout_type; + + const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(args[0]); + + common_hal_nativeio_analogout_construct(self, pin); + + return self; +} + +//| .. method:: deinit() +//| +//| Turn off the AnalogOut and release the pin for other use. +//| +STATIC mp_obj_t nativeio_analogout_deinit(mp_obj_t self_in) { + nativeio_analogout_obj_t *self = self_in; + + common_hal_nativeio_analogout_deinit(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(nativeio_analogout_deinit_obj, nativeio_analogout_deinit); + +//| .. attribute:: value +//| +//| The value on the analog pin. The value must be between 0 and 65535 +//| inclusive (16-bit). Even if the underlying digital to analog converter +//| is lower resolution, the input must be scaled to be 16-bit. +//| +//| :return: the last value written +//| :rtype: int +//| +STATIC mp_obj_t nativeio_analogout_obj_set_value(mp_obj_t self_in, mp_obj_t value) { + nativeio_analogout_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_analogout_set_value(self, mp_obj_get_int(value)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_analogout_set_value_obj, nativeio_analogout_obj_set_value); + +mp_obj_property_t nativeio_analogout_value_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&nativeio_analogout_set_value_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t nativeio_analogout_locals_dict_table[] = { + // instance methods + { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&nativeio_analogout_deinit_obj }, + + // Properties + { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&nativeio_analogout_value_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_analogout_locals_dict, nativeio_analogout_locals_dict_table); + +const mp_obj_type_t nativeio_analogout_type = { + { &mp_type_type }, + .name = MP_QSTR_AnalogOut, + .make_new = nativeio_analogout_make_new, + .locals_dict = (mp_obj_t)&nativeio_analogout_locals_dict, +}; diff --git a/shared-bindings/nativeio/AnalogOut.h b/shared-bindings/nativeio/AnalogOut.h new file mode 100644 index 0000000000..195e4c313f --- /dev/null +++ b/shared-bindings/nativeio/AnalogOut.h @@ -0,0 +1,39 @@ +/* + * 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_SHARED_BINDINGS_NATIVEIO_ANALOGOUT_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGOUT_H__ + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +extern const mp_obj_type_t nativeio_analogout_type; + +void common_hal_nativeio_analogout_construct(nativeio_analogout_obj_t* self, const mcu_pin_obj_t *pin); +void common_hal_nativeio_analogout_deinit(nativeio_analogout_obj_t *self); +void common_hal_nativeio_analogout_set_value(nativeio_analogout_obj_t *self, uint16_t value); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_ANALOGOUT_H__ diff --git a/shared-bindings/nativeio/DigitalInOut.c b/shared-bindings/nativeio/DigitalInOut.c new file mode 100644 index 0000000000..ce1e129861 --- /dev/null +++ b/shared-bindings/nativeio/DigitalInOut.c @@ -0,0 +1,445 @@ +/* + * 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 +#include + +#include "py/nlr.h" +#include "py/objtype.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/mphal.h" + +#include "shared-bindings/nativeio/DigitalInOut.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`DigitalInOut` -- digital input and output +//| ========================================================= +//| +//| A DigitalInOut is used to digitally control I/O pins. For analog control of +//| a pin, see the :py:class:`~nativeio.AnalogIn` and +//| :py:class:`~nativeio.AnalogOut` classes. +//| + +//| .. class:: DigitalInOut(pin) +//| +//| Create a new DigitalInOut object associated with the pin. Defaults to input +//| with no pull. Use :py:meth:`switch_to_input` and +//| :py:meth:`switch_to_output` to change the direction. +//| +//| :param ~microcontroller.Pin pin: The pin to control +//| +STATIC mp_obj_t nativeio_digitalinout_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); + + nativeio_digitalinout_obj_t *self = m_new_obj(nativeio_digitalinout_obj_t); + self->base.type = &nativeio_digitalinout_type; + + mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(args[0]); + common_hal_nativeio_digitalinout_construct(self, pin); + + return (mp_obj_t)self; +} + +//| .. method:: deinit() +//| +//| Turn off the DigitalInOut and release the pin for other use. +//| +STATIC mp_obj_t nativeio_digitalinout_obj_deinit(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_digitalinout_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_deinit_obj, nativeio_digitalinout_obj_deinit); + +//| .. method:: __enter__() +//| +//| No-op used by Context Managers. +//| +STATIC mp_obj_t nativeio_digitalinout_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout___enter___obj, nativeio_digitalinout_obj___enter__); + +//| .. method:: __exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. +//| +STATIC mp_obj_t nativeio_digitalinout_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_nativeio_digitalinout_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_digitalinout_obj___exit___obj, 4, 4, nativeio_digitalinout_obj___exit__); + +//| +//| .. method:: switch_to_output(value=False, drive_mode=DriveMode.push_pull) +//| +//| Switch to writing out digital values. +//| +//| :param bool value: default value to set upon switching +//| :param DriveMode push_pull: drive mode for the output +//| +typedef struct { + mp_obj_base_t base; +} nativeio_digitalinout_drive_mode_obj_t; +extern const nativeio_digitalinout_drive_mode_obj_t nativeio_digitalinout_drive_mode_push_pull_obj; +extern const nativeio_digitalinout_drive_mode_obj_t nativeio_digitalinout_drive_mode_open_drain_obj; + +STATIC mp_obj_t nativeio_digitalinout_switch_to_output(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_value, ARG_drive_mode }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_drive_mode, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = &nativeio_digitalinout_drive_mode_push_pull_obj} }, + }; + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + enum digitalinout_drive_mode_t drive_mode = DRIVE_MODE_PUSH_PULL; + if (args[ARG_drive_mode].u_rom_obj == &nativeio_digitalinout_drive_mode_open_drain_obj) { + drive_mode = DRIVE_MODE_OPEN_DRAIN; + } + // do the transfer + common_hal_nativeio_digitalinout_switch_to_output(self, args[ARG_value].u_bool, drive_mode); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(nativeio_digitalinout_switch_to_output_obj, 1, nativeio_digitalinout_switch_to_output); + +//| .. method:: switch_to_input(pull=None) +//| +//| Switch to read in digital values. +//| +//| :param Pull pull: pull configuration for the input +//| +typedef struct { + mp_obj_base_t base; +} nativeio_digitalinout_pull_obj_t; +extern const nativeio_digitalinout_pull_obj_t nativeio_digitalinout_pull_up_obj; +extern const nativeio_digitalinout_pull_obj_t nativeio_digitalinout_pull_down_obj; + +STATIC mp_obj_t nativeio_digitalinout_switch_to_input(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_pull }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = mp_const_none} }, + }; + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + enum digitalinout_pull_t pull = PULL_NONE; + if (args[ARG_pull].u_rom_obj == &nativeio_digitalinout_pull_up_obj) { + pull = PULL_UP; + }else if (args[ARG_pull].u_rom_obj == &nativeio_digitalinout_pull_down_obj) { + pull = PULL_DOWN; + } + // do the transfer + common_hal_nativeio_digitalinout_switch_to_input(self, pull); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(nativeio_digitalinout_switch_to_input_obj, 1, nativeio_digitalinout_switch_to_input); + +//| .. attribute:: direction +//| +//| Get the direction of the pin. +//| +//| :raises AttributeError: when set. Use :py:meth:`switch_to_input` and :py:meth:`switch_to_output` to change the direction. +//| +typedef struct { + mp_obj_base_t base; +} nativeio_digitalinout_direction_obj_t; +extern const nativeio_digitalinout_direction_obj_t nativeio_digitalinout_direction_in_obj; +extern const nativeio_digitalinout_direction_obj_t nativeio_digitalinout_direction_out_obj; + +STATIC mp_obj_t nativeio_digitalinout_obj_get_direction(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + enum digitalinout_direction_t direction = common_hal_nativeio_digitalinout_get_direction(self); + if (direction == DIRECTION_IN) { + return (mp_obj_t)&nativeio_digitalinout_direction_in_obj; + } + return (mp_obj_t)&nativeio_digitalinout_direction_out_obj; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_get_direction_obj, nativeio_digitalinout_obj_get_direction); + +mp_obj_property_t nativeio_digitalinout_direction_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_digitalinout_get_direction_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. attribute:: value +//| +//| Get or set the digital logic level of the pin. +//| +STATIC mp_obj_t nativeio_digitalinout_obj_get_value(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + bool value = common_hal_nativeio_digitalinout_get_value(self); + return mp_obj_new_bool(value); +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_get_value_obj, nativeio_digitalinout_obj_get_value); + +STATIC mp_obj_t nativeio_digitalinout_obj_set_value(mp_obj_t self_in, mp_obj_t value) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_IN) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Cannot set value when direction is input.")); + return mp_const_none; + } + common_hal_nativeio_digitalinout_set_value(self, mp_obj_is_true(value)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_digitalinout_set_value_obj, nativeio_digitalinout_obj_set_value); + +mp_obj_property_t nativeio_digitalinout_value_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_digitalinout_get_value_obj, + (mp_obj_t)&nativeio_digitalinout_set_value_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. attribute:: drive_mode +//| +//| Get or set the pin drive mode. +//| +STATIC mp_obj_t nativeio_digitalinout_obj_get_drive_mode(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_IN) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Drive mode not used when direction is input.")); + return mp_const_none; + } + enum digitalinout_drive_mode_t drive_mode = common_hal_nativeio_digitalinout_get_drive_mode(self); + if (drive_mode == DRIVE_MODE_PUSH_PULL) { + return (mp_obj_t)&nativeio_digitalinout_drive_mode_push_pull_obj; + } + return (mp_obj_t)&nativeio_digitalinout_drive_mode_open_drain_obj; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_get_drive_mode_obj, nativeio_digitalinout_obj_get_drive_mode); + +STATIC mp_obj_t nativeio_digitalinout_obj_set_drive_mode(mp_obj_t self_in, mp_obj_t drive_mode) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_IN) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Drive mode not used when direction is input.")); + return mp_const_none; + } + enum digitalinout_drive_mode_t c_drive_mode = DRIVE_MODE_PUSH_PULL; + if (drive_mode == &nativeio_digitalinout_drive_mode_open_drain_obj) { + c_drive_mode = DRIVE_MODE_OPEN_DRAIN; + } + common_hal_nativeio_digitalinout_set_drive_mode(self, c_drive_mode); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_digitalinout_set_drive_mode_obj, nativeio_digitalinout_obj_set_drive_mode); + +mp_obj_property_t nativeio_digitalinout_drive_mode_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_digitalinout_get_drive_mode_obj, + (mp_obj_t)&nativeio_digitalinout_set_drive_mode_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. attribute:: pull +//| +//| Get or set the pin pull. +//| +//| :raises AttributeError: if the direction is `out`. +//| +STATIC mp_obj_t nativeio_digitalinout_obj_get_pull(mp_obj_t self_in) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_OUT) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Pull not used when direction is output.")); + return mp_const_none; + } + enum digitalinout_pull_t pull = common_hal_nativeio_digitalinout_get_pull(self); + if (pull == PULL_UP) { + return (mp_obj_t)&nativeio_digitalinout_pull_up_obj; + } else if (pull == PULL_DOWN) { + return (mp_obj_t)&nativeio_digitalinout_pull_down_obj; + } + return (mp_obj_t)&mp_const_none_obj; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_digitalinout_get_pull_obj, nativeio_digitalinout_obj_get_pull); + +STATIC mp_obj_t nativeio_digitalinout_obj_set_pull(mp_obj_t self_in, mp_obj_t pull) { + nativeio_digitalinout_obj_t *self = MP_OBJ_TO_PTR(self_in); + if (common_hal_nativeio_digitalinout_get_direction(self) == DIRECTION_OUT) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "Pull not used when direction is output.")); + return mp_const_none; + } + common_hal_nativeio_digitalinout_set_pull(self, (enum digitalinout_pull_t) MP_OBJ_SMALL_INT_VALUE(pull)); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_digitalinout_set_pull_obj, nativeio_digitalinout_obj_set_pull); + +mp_obj_property_t nativeio_digitalinout_pull_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_digitalinout_get_pull_obj, + (mp_obj_t)&nativeio_digitalinout_set_pull_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +//| .. class:: microcontroller.DigitalInOut.Direction +//| +//| Enum-like class to define which direction the digital values are +//| going. +//| +//| .. data:: in +//| +//| Read digital data in +//| +//| .. data:: out +//| +//| Write digital data out +//| +const mp_obj_type_t nativeio_digitalinout_direction_type; + +const nativeio_digitalinout_direction_obj_t nativeio_digitalinout_direction_in_obj = { + { &nativeio_digitalinout_direction_type }, +}; + +const nativeio_digitalinout_direction_obj_t nativeio_digitalinout_direction_out_obj = { + { &nativeio_digitalinout_direction_type }, +}; + +STATIC const mp_rom_map_elem_t nativeio_digitalinout_direction_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_in), MP_ROM_PTR(&nativeio_digitalinout_direction_in_obj) }, + { MP_ROM_QSTR(MP_QSTR_out), MP_ROM_PTR(&nativeio_digitalinout_direction_out_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_digitalinout_direction_locals_dict, nativeio_digitalinout_direction_locals_dict_table); + +const mp_obj_type_t nativeio_digitalinout_direction_type = { + { &mp_type_type }, + .name = MP_QSTR_Direction, + .locals_dict = (mp_obj_t)&nativeio_digitalinout_direction_locals_dict, +}; + +//| .. class:: nativeio.DigitalInOut.DriveMode +//| +//| Enum-like class to define the drive mode used when outputting +//| digital values. +//| +//| .. data:: push_pull +//| +//| Output both high and low digital values +//| +//| .. data:: open_drain +//| +//| Output low digital values but go into high z for digital high. This is +//| useful for i2c and other protocols that share a digital line. +//| +const mp_obj_type_t nativeio_digitalinout_drive_mode_type; + +const nativeio_digitalinout_drive_mode_obj_t nativeio_digitalinout_drive_mode_push_pull_obj = { + { &nativeio_digitalinout_drive_mode_type }, +}; + +const nativeio_digitalinout_drive_mode_obj_t nativeio_digitalinout_drive_mode_open_drain_obj = { + { &nativeio_digitalinout_drive_mode_type }, +}; + +STATIC const mp_rom_map_elem_t nativeio_digitalinout_drive_mode_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_push_pull), MP_ROM_PTR(&nativeio_digitalinout_drive_mode_push_pull_obj) }, + { MP_ROM_QSTR(MP_QSTR_open_drain), MP_ROM_PTR(&nativeio_digitalinout_drive_mode_open_drain_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_digitalinout_drive_mode_locals_dict, nativeio_digitalinout_drive_mode_locals_dict_table); + +const mp_obj_type_t nativeio_digitalinout_drive_mode_type = { + { &mp_type_type }, + .name = MP_QSTR_DriveMode, + .locals_dict = (mp_obj_t)&nativeio_digitalinout_drive_mode_locals_dict, +}; + +//| .. class:: nativeio.DigitalInOut.Pull +//| +//| Enum-like class to define the pull value, if any, used while reading +//| digital values in. +//| +//| .. data:: up +//| +//| When the input line isn't being driven the pull up can pull the state +//| of the line high so it reads as true. +//| +//| .. data:: down +//| +//| When the input line isn't being driven the pull down can pull the +//| state of the line low so it reads as false. +//| +const mp_obj_type_t nativeio_digitalinout_pull_type; + +const nativeio_digitalinout_pull_obj_t nativeio_digitalinout_pull_up_obj = { + { &nativeio_digitalinout_pull_type }, +}; + +const nativeio_digitalinout_pull_obj_t nativeio_digitalinout_pull_down_obj = { + { &nativeio_digitalinout_pull_type }, +}; + +STATIC const mp_rom_map_elem_t nativeio_digitalinout_pull_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_up), MP_ROM_PTR(&nativeio_digitalinout_pull_up_obj) }, + { MP_ROM_QSTR(MP_QSTR_down), MP_ROM_PTR(&nativeio_digitalinout_pull_down_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_digitalinout_pull_locals_dict, nativeio_digitalinout_pull_locals_dict_table); + +const mp_obj_type_t nativeio_digitalinout_pull_type = { + { &mp_type_type }, + .name = MP_QSTR_Pull, + .locals_dict = (mp_obj_t)&nativeio_digitalinout_pull_locals_dict, +}; + +STATIC const mp_rom_map_elem_t nativeio_digitalinout_locals_dict_table[] = { + // instance methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_digitalinout_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&nativeio_digitalinout___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&nativeio_digitalinout_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_switch_to_output), MP_ROM_PTR(&nativeio_digitalinout_switch_to_output_obj) }, + { MP_ROM_QSTR(MP_QSTR_switch_to_input), MP_ROM_PTR(&nativeio_digitalinout_switch_to_input_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_direction), MP_ROM_PTR(&nativeio_digitalinout_direction_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&nativeio_digitalinout_value_obj) }, + { MP_ROM_QSTR(MP_QSTR_drive_mode), MP_ROM_PTR(&nativeio_digitalinout_drive_mode_obj) }, + { MP_ROM_QSTR(MP_QSTR_pull), MP_ROM_PTR(&nativeio_digitalinout_pull_obj) }, + + // Nested Enum-like Classes. + { MP_ROM_QSTR(MP_QSTR_Direction), MP_ROM_PTR(&nativeio_digitalinout_direction_type) }, + { MP_ROM_QSTR(MP_QSTR_DriveMode), MP_ROM_PTR(&nativeio_digitalinout_drive_mode_type) }, + { MP_ROM_QSTR(MP_QSTR_Pull), MP_ROM_PTR(&nativeio_digitalinout_pull_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_digitalinout_locals_dict, nativeio_digitalinout_locals_dict_table); + +const mp_obj_type_t nativeio_digitalinout_type = { + { &mp_type_type }, + .name = MP_QSTR_DigitalInOut, + .make_new = nativeio_digitalinout_make_new, + .locals_dict = (mp_obj_t)&nativeio_digitalinout_locals_dict, +}; diff --git a/shared-bindings/nativeio/DigitalInOut.h b/shared-bindings/nativeio/DigitalInOut.h new file mode 100644 index 0000000000..b712a811cd --- /dev/null +++ b/shared-bindings/nativeio/DigitalInOut.h @@ -0,0 +1,68 @@ +/* + * 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_SHARED_BINDINGS_NATIVEIO_DIGITALINOUT_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_DIGITALINOUT_H__ + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +extern const mp_obj_type_t nativeio_digitalinout_type; + +enum digitalinout_direction_t { + DIRECTION_IN, + DIRECTION_OUT +}; + +enum digitalinout_pull_t { + PULL_NONE, + PULL_UP, + PULL_DOWN +}; + +enum digitalinout_drive_mode_t { + DRIVE_MODE_PUSH_PULL, + DRIVE_MODE_OPEN_DRAIN +}; + +typedef enum { + DIGITALINOUT_OK, + DIGITALINOUT_PIN_BUSY +} digitalinout_result_t; + +digitalinout_result_t common_hal_nativeio_digitalinout_construct(nativeio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin); +void common_hal_nativeio_digitalinout_deinit(nativeio_digitalinout_obj_t* self); +void common_hal_nativeio_digitalinout_switch_to_input(nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull); +void common_hal_nativeio_digitalinout_switch_to_output(nativeio_digitalinout_obj_t* self, bool value, enum digitalinout_drive_mode_t drive_mode); +enum digitalinout_direction_t common_hal_nativeio_digitalinout_get_direction(nativeio_digitalinout_obj_t* self); +void common_hal_nativeio_digitalinout_set_value(nativeio_digitalinout_obj_t* self, bool value); +bool common_hal_nativeio_digitalinout_get_value(nativeio_digitalinout_obj_t* self); +void common_hal_nativeio_digitalinout_set_drive_mode(nativeio_digitalinout_obj_t* self, enum digitalinout_drive_mode_t drive_mode); +enum digitalinout_drive_mode_t common_hal_nativeio_digitalinout_get_drive_mode(nativeio_digitalinout_obj_t* self); +void common_hal_nativeio_digitalinout_set_pull(nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull); +enum digitalinout_pull_t common_hal_nativeio_digitalinout_get_pull(nativeio_digitalinout_obj_t* self); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_DIGITALINOUT_H__ diff --git a/shared-bindings/nativeio/I2C.c b/shared-bindings/nativeio/I2C.c new file mode 100644 index 0000000000..325d7c56b9 --- /dev/null +++ b/shared-bindings/nativeio/I2C.c @@ -0,0 +1,180 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// This file contains all of the Python API definitions for the +// nativeio.I2C class. + +#include "shared-bindings/nativeio/I2C.h" + +#include "py/runtime.h" +//| .. currentmodule:: nativeio +//| +//| :class:`I2C` --- Two wire serial protocol +//| ------------------------------------------ +//| +//| .. class:: I2C(scl, sda, \*, freq=400000) +//| +//| I2C is a two-wire protocol for communicating between devices. At the +//| physical level it consists of 2 wires: SCL and SDA, the clock and data +//| lines respectively. +//| +//| :param ~microcontroller.Pin scl: The clock pin +//| :param ~microcontroller.Pin sda: The data pin +//| :param int freq: The clock frequency +//| +STATIC mp_obj_t nativeio_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + nativeio_i2c_obj_t *self = m_new_obj(nativeio_i2c_obj_t); + self->base.type = &nativeio_i2c_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_scl, ARG_sda, ARG_freq }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + }; + 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); + const mcu_pin_obj_t* scl = MP_OBJ_TO_PTR(args[ARG_scl].u_obj); + const mcu_pin_obj_t* sda = MP_OBJ_TO_PTR(args[ARG_sda].u_obj); + common_hal_nativeio_i2c_construct(self, scl, sda, args[ARG_freq].u_int); + return (mp_obj_t)self; +} + +//| .. method:: I2C.deinit() +//| +//| Releases control of the underlying hardware so other classes can use it. +//| +STATIC mp_obj_t nativeio_i2c_obj_deinit(mp_obj_t self_in) { + nativeio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_i2c_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_i2c_deinit_obj, nativeio_i2c_obj_deinit); + +//| .. method:: I2C.__enter__() +//| +//| No-op used in Context Managers. +//| +STATIC mp_obj_t nativeio_i2c_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_i2c___enter___obj, nativeio_i2c_obj___enter__); + +//| .. method:: I2C.__exit__() +//| +//| Automatically deinitializes the hardware on context exit. +//| +STATIC mp_obj_t nativeio_i2c_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_nativeio_i2c_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_i2c_obj___exit___obj, 4, 4, nativeio_i2c_obj___exit__); + +//| .. method:: I2C.scan() +//| +//| Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of +//| those that respond. A device responds if it pulls the SDA line low after +//| its address (including a read bit) is sent on the bus. +//| +STATIC mp_obj_t nativeio_i2c_scan(mp_obj_t self_in) { + nativeio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t list = mp_obj_new_list(0, NULL); + // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved + for (int addr = 0x08; addr < 0x78; ++addr) { + bool success = common_hal_nativeio_i2c_probe(self, addr); + if (success) { + mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); + } + } + return list; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_i2c_scan_obj, nativeio_i2c_scan); + +//| .. method:: I2C.readfrom_into(address, buffer) +//| +//| Read into ``buffer`` from the slave specified by ``address``. +//| The number of bytes read will be the length of `buf`. +//| +STATIC mp_obj_t nativeio_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { + nativeio_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); + common_hal_nativeio_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_3(nativeio_i2c_readfrom_into_obj, nativeio_i2c_readfrom_into); + +//| .. method:: I2C.writeto(address, buffer, stop=True) +//| +//| Write the bytes from ``buffer`` to the slave specified by ``address``. +//| Transmits a stop bit if ``stop`` is set. +//| +STATIC mp_obj_t nativeio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_address, ARG_buffer, ARG_stop }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_stop, MP_ARG_BOOL, {.u_bool = true} }, + }; + nativeio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // get the buffer to write the data from + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ); + + // do the transfer + bool ok = common_hal_nativeio_i2c_write(self, args[ARG_address].u_int, + bufinfo.buf, bufinfo.len, args[ARG_stop].u_bool); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(nativeio_i2c_writeto_obj, 1, nativeio_i2c_writeto); + +STATIC const mp_rom_map_elem_t nativeio_i2c_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_i2c_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&nativeio_i2c___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&nativeio_i2c_obj___exit___obj) }, + { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&nativeio_i2c_scan_obj) }, + + { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&nativeio_i2c_readfrom_into_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&nativeio_i2c_writeto_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_i2c_locals_dict, nativeio_i2c_locals_dict_table); + +const mp_obj_type_t nativeio_i2c_type = { + { &mp_type_type }, + .name = MP_QSTR_I2C, + .make_new = nativeio_i2c_make_new, + .locals_dict = (mp_obj_dict_t*)&nativeio_i2c_locals_dict, +}; diff --git a/shared-bindings/nativeio/I2C.h b/shared-bindings/nativeio/I2C.h new file mode 100644 index 0000000000..9f90de5368 --- /dev/null +++ b/shared-bindings/nativeio/I2C.h @@ -0,0 +1,64 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// Machine is the HAL for low-level, hardware accelerated functions. It is not +// meant to simplify APIs, its only meant to unify them so that other modules +// do not require port specific logic. +// +// This file includes externs for all functions a port should implement to +// support the machine module. + +#ifndef __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_I2C_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_I2C_H__ + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t nativeio_i2c_type; + +// Initializes the hardware peripheral. +extern void common_hal_nativeio_i2c_construct(nativeio_i2c_obj_t *self, + const mcu_pin_obj_t * scl, + const mcu_pin_obj_t * sda, + uint32_t freq); + +extern void common_hal_nativeio_i2c_deinit(nativeio_i2c_obj_t *self); + +// Probe the bus to see if a device acknowledges the given address. +extern bool common_hal_nativeio_i2c_probe(nativeio_i2c_obj_t *self, uint8_t addr); + +extern bool common_hal_nativeio_i2c_write(nativeio_i2c_obj_t *self, uint16_t address, + const uint8_t * data, size_t len, + bool stop); + +// Reads memory of the i2c device picking up where it left off. +extern bool common_hal_nativeio_i2c_read(nativeio_i2c_obj_t *self, uint16_t address, + uint8_t * data, size_t len); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_I2C_H__ diff --git a/shared-bindings/nativeio/PWMOut.c b/shared-bindings/nativeio/PWMOut.c new file mode 100644 index 0000000000..13897ad1d4 --- /dev/null +++ b/shared-bindings/nativeio/PWMOut.c @@ -0,0 +1,151 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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 + +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/nativeio/PWMOut.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`PWMOut` -- Output a Pulse Width Modulated signal +//| ======================================================== +//| +//| PWMOut can be used to output a PWM signal on a given pin. +//| +//| .. class:: PWMOut(pin, duty=0) +//| +//| Create a PWM object associated with the given pin. This allows you to +//| write PWM signals out on the given pin. Frequency is currently fixed at +//| ~735Hz like Arduino. +//| +//| :param ~microcontroller.Pin pin: The pin to output to +//| +STATIC mp_obj_t nativeio_pwmout_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true); + mp_obj_t pin_obj = args[0]; + const mcu_pin_obj_t *pin = MP_OBJ_TO_PTR(pin_obj); + + // create PWM object from the given pin + nativeio_pwmout_obj_t *self = m_new_obj(nativeio_pwmout_obj_t); + self->base.type = &nativeio_pwmout_type; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + enum { ARG_duty }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_duty, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} }, + }; + mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, args + 1, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args); + uint8_t duty = parsed_args[ARG_duty].u_int; + + common_hal_nativeio_pwmout_construct(self, pin, duty); + + return MP_OBJ_FROM_PTR(self); +} + +//| .. method:: deinit() +//| +//| Deinitialises the PWMOut and releases any hardware resources for reuse. +//| +STATIC mp_obj_t nativeio_pwmout_deinit(mp_obj_t self_in) { + nativeio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_pwmout_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(nativeio_pwmout_deinit_obj, nativeio_pwmout_deinit); + +//| .. method:: __enter__() +//| +//| No-op used by Context Managers. +//| +STATIC mp_obj_t nativeio_pwmout_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_pwmout___enter___obj, nativeio_pwmout_obj___enter__); + +//| .. method:: __exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. +//| +STATIC mp_obj_t nativeio_pwmout_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_nativeio_pwmout_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_pwmout_obj___exit___obj, 4, 4, nativeio_pwmout_obj___exit__); + +//| .. attribute:: duty_cycle +//| +//| 8 bit value that dictates how much of one cycle is high (1) versus low +//| (0). 255 will always be high, 0 will always be low and 127 will be half +//| high and then half low. +STATIC mp_obj_t nativeio_pwmout_obj_get_duty_cycle(mp_obj_t self_in) { + nativeio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); + return MP_OBJ_NEW_SMALL_INT(common_hal_nativeio_pwmout_get_duty_cycle(self)); +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_pwmout_get_duty_cycle_obj, nativeio_pwmout_obj_get_duty_cycle); + +STATIC mp_obj_t nativeio_pwmout_obj_set_duty_cycle(mp_obj_t self_in, mp_obj_t duty_cycle) { + nativeio_pwmout_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_int_t duty = mp_obj_get_int(duty_cycle); + if (duty < 0 || duty > 255) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "PWM duty must be between 0 and 255 (8 bit resolution), not %d", + duty)); + } + common_hal_nativeio_pwmout_set_duty_cycle(self, duty); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_pwmout_set_duty_cycle_obj, nativeio_pwmout_obj_set_duty_cycle); + +mp_obj_property_t nativeio_pwmout_duty_cycle_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&nativeio_pwmout_get_duty_cycle_obj, + (mp_obj_t)&nativeio_pwmout_set_duty_cycle_obj, + (mp_obj_t)&mp_const_none_obj}, +}; + +STATIC const mp_rom_map_elem_t nativeio_pwmout_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_pwmout_deinit_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_duty_cycle), MP_ROM_PTR(&nativeio_pwmout_duty_cycle_obj) }, + // TODO(tannewt): Add frequency. + // TODO(tannewt): Add enabled to determine whether the signal is output + // without giving up the resources. Useful for IR output. +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_pwmout_locals_dict, nativeio_pwmout_locals_dict_table); + +const mp_obj_type_t nativeio_pwmout_type = { + { &mp_type_type }, + .name = MP_QSTR_PWMOut, + .make_new = nativeio_pwmout_make_new, + .locals_dict = (mp_obj_dict_t*)&nativeio_pwmout_locals_dict, +}; diff --git a/shared-bindings/nativeio/PWMOut.h b/shared-bindings/nativeio/PWMOut.h new file mode 100644 index 0000000000..0be553315d --- /dev/null +++ b/shared-bindings/nativeio/PWMOut.h @@ -0,0 +1,40 @@ +/* + * 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_SHARED_BINDINGS_NATIVEIO_PWMOUT_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_PWMOUT_H__ + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +extern const mp_obj_type_t nativeio_pwmout_type; + +extern void common_hal_nativeio_pwmout_construct(nativeio_pwmout_obj_t* self, const mcu_pin_obj_t* pin, uint16_t duty); +extern void common_hal_nativeio_pwmout_deinit(nativeio_pwmout_obj_t* self); +extern void common_hal_nativeio_pwmout_set_duty_cycle(nativeio_pwmout_obj_t* self, uint16_t duty); +extern uint16_t common_hal_nativeio_pwmout_get_duty_cycle(nativeio_pwmout_obj_t* self); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_PWMOUT_H__ diff --git a/shared-bindings/nativeio/SPI.c b/shared-bindings/nativeio/SPI.c new file mode 100644 index 0000000000..f17814ffa9 --- /dev/null +++ b/shared-bindings/nativeio/SPI.c @@ -0,0 +1,167 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// This file contains all of the Python API definitions for the +// nativeio.SPI class. + +#include + +#include "shared-bindings/nativeio/SPI.h" + +#include "py/runtime.h" + +//| .. currentmodule:: nativeio +//| +//| :class:`SPI` -- a 3-4 wire serial protocol +//| ----------------------------------------------- +//| +//| SPI is a serial protocol that has exclusive pins for data in and out of the +//| master. It is typically faster than :py:class:`~nativeio.I2C` because a +//| separate pin is used to control the active slave rather than a transitted +//| address. This class only manages three of the four SPI lines: `!clock`, +//| `!MOSI`, `!MISO`. Its up to the client to manage the appropriate slave +//| select line. (This is common because multiple slaves can share the `!clock`, +//| `!MOSI` and `!MISO` lines and therefore the hardware.) +//| +//| .. class:: SPI(clock, MOSI, MISO, baudrate=1000000) +//| +//| Construct an SPI object on the given pins. +//| +//| :param ~microcontroller.Pin clock: the pin to use for the clock. +//| :param ~microcontroller.Pin MOSI: the Master Out Slave In pin. +//| :param ~microcontroller.Pin MISO: the Master In Slave Out pin. +//| :param int baudrate: is the SCK clock rate. +//| + +// TODO(tannewt): Support LSB SPI. +// TODO(tannewt): Support phase, polarity and bit order. +STATIC mp_obj_t nativeio_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + nativeio_spi_obj_t *self = m_new_obj(nativeio_spi_obj_t); + self->base.type = &nativeio_spi_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + enum { ARG_clock, ARG_MOSI, ARG_MISO, ARG_baudrate, ARG_polarity, ARG_phase, ARG_bits, ARG_firstbit }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_clock, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MOSI, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_MISO, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} }, + { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_phase, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, + }; + 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); + const mcu_pin_obj_t* clock = MP_OBJ_TO_PTR(args[ARG_clock].u_obj); + const mcu_pin_obj_t* mosi = MP_OBJ_TO_PTR(args[ARG_MOSI].u_obj); + const mcu_pin_obj_t* miso = MP_OBJ_TO_PTR(args[ARG_MISO].u_obj); + common_hal_nativeio_spi_construct(self, clock, mosi, miso, args[ARG_baudrate].u_int); + return (mp_obj_t)self; +} + +//| .. method:: SPI.deinit() +//| +//| Turn off the SPI bus. +//| +STATIC mp_obj_t nativeio_spi_obj_deinit(mp_obj_t self_in) { + nativeio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + common_hal_nativeio_spi_deinit(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_spi_deinit_obj, nativeio_spi_obj_deinit); + +//| .. method:: SPI.__enter__() +//| +//| No-op used by Context Managers. +//| +STATIC mp_obj_t nativeio_spi_obj___enter__(mp_obj_t self_in) { + return self_in; +} +MP_DEFINE_CONST_FUN_OBJ_1(nativeio_spi___enter___obj, nativeio_spi_obj___enter__); + +//| .. method:: SPI.__exit__() +//| +//| Automatically deinitializes the hardware when exiting a context. +//| +STATIC mp_obj_t nativeio_spi_obj___exit__(size_t n_args, const mp_obj_t *args) { + (void)n_args; + common_hal_nativeio_spi_deinit(args[0]); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_spi_obj___exit___obj, 4, 4, nativeio_spi_obj___exit__); + +//| .. method:: SPI.write(buf) +//| +//| Write the data contained in `!buf`. +//| Returns the number of bytes written. +//| +STATIC mp_obj_t nativeio_spi_write(mp_obj_t self_in, mp_obj_t wr_buf) { + mp_buffer_info_t src; + mp_get_buffer_raise(wr_buf, &src, MP_BUFFER_READ); + nativeio_spi_obj_t *self = MP_OBJ_TO_PTR(self_in); + bool ok = common_hal_nativeio_spi_write(self, src.buf, src.len); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "SPI bus error")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_2(nativeio_spi_write_obj, nativeio_spi_write); + + +//| .. method:: SPI.readinto(buf) +//| +//| Read into the buffer specified by `!buf` while writing the data +//| specified by `!write`. +//| Return the number of bytes read. +//| +STATIC mp_obj_t nativeio_spi_readinto(size_t n_args, const mp_obj_t *args) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_WRITE); + bool ok = common_hal_nativeio_spi_read(args[0], bufinfo.buf, bufinfo.len); + if (!ok) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "SPI bus error")); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(nativeio_spi_readinto_obj, 2, 2, nativeio_spi_readinto); + +STATIC const mp_rom_map_elem_t nativeio_spi_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&nativeio_spi_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&nativeio_spi___enter___obj) }, + { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&nativeio_spi_obj___exit___obj) }, + + { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&nativeio_spi_readinto_obj) }, + { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&nativeio_spi_write_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(nativeio_spi_locals_dict, nativeio_spi_locals_dict_table); + +const mp_obj_type_t nativeio_spi_type = { + { &mp_type_type }, + .name = MP_QSTR_SPI, + .make_new = nativeio_spi_make_new, + .locals_dict = (mp_obj_dict_t*)&nativeio_spi_locals_dict, +}; diff --git a/shared-bindings/nativeio/SPI.h b/shared-bindings/nativeio/SPI.h new file mode 100644 index 0000000000..ca1a8c5d44 --- /dev/null +++ b/shared-bindings/nativeio/SPI.h @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_SHARED_BINDINGS_NATIVEIO_SPI_H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_SPI_H__ + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "common-hal/nativeio/types.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t nativeio_spi_type; + +// Construct an underlying SPI object. +extern void common_hal_nativeio_spi_construct(nativeio_spi_obj_t *self, + const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, + const mcu_pin_obj_t * miso, uint32_t baudrate); + +extern void common_hal_nativeio_spi_deinit(nativeio_spi_obj_t *self); + +// Writes out the given data. +extern bool common_hal_nativeio_spi_write(nativeio_spi_obj_t *self, const uint8_t *data, size_t len); + +// Reads in len bytes while outputting zeroes. +extern bool common_hal_nativeio_spi_read(nativeio_spi_obj_t *self, uint8_t *data, size_t len); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO_SPI_H__ diff --git a/shared-bindings/nativeio/__init__.c b/shared-bindings/nativeio/__init__.c new file mode 100644 index 0000000000..8f9819778c --- /dev/null +++ b/shared-bindings/nativeio/__init__.c @@ -0,0 +1,122 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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. + */ + +// nativeio is the HAL for low-level, hardware accelerated classes. It +// is not meant to simplify APIs, its only meant to unify them so that other +// libraries do not require port specific logic. + +#include + +#include "py/obj.h" +#include "py/runtime.h" + +#include "shared-bindings/microcontroller/Pin.h" +#include "shared-bindings/nativeio/__init__.h" +#include "shared-bindings/nativeio/AnalogIn.h" +#include "shared-bindings/nativeio/AnalogOut.h" +#include "shared-bindings/nativeio/DigitalInOut.h" +#include "shared-bindings/nativeio/I2C.h" +#include "shared-bindings/nativeio/PWMOut.h" +#include "shared-bindings/nativeio/SPI.h" +#include "common-hal/nativeio/types.h" +#include "shared-bindings/nativeio/__init__.h" + +#include "py/runtime.h" + +//| :mod:`nativeio` --- Hardware accelerated behavior +//| ================================================= +//| +//| .. module:: nativeio +//| :synopsis: Hardware accelerated behavior +//| :platform: SAMD21 +//| +//| The `nativeio` module contains classes to provide access to IO accelerated +//| by hardware on the onboard microcontroller. The classes are meant to align +//| with commonly hardware accelerated IO and not necessarily match up with +//| microcontroller structure (because it varies). +//| +//| If the microcontroller doesn't not support the behavior in a hardware +//| accelerated fashion it throws a NotImplementedError on construction. Use +//| `bitbangio` module instead which only depends on +//| :py:class:`~nativeio.DigitalInOut` and is shared across hardware ports. +//| +//| Libraries +//| +//| .. toctree:: +//| :maxdepth: 3 +//| +//| AnalogIn +//| AnalogOut +//| DigitalInOut +//| I2C +//| PWMOut +//| SPI +//| +//| All libraries change hardware state and should be deinitialized when they +//| are no longer needed. To do so, either call :py:meth:`!deinit` or use a +//| context manager. +//| +//| For example:: +//| +//| import nativeio +//| from board import * +//| +//| with nativeio.I2C(SCL, SDA) as i2c: +//| i2c.scan() +//| +//| This example will initialize the the device, run +//| :py:meth:`~nativeio.I2C.scan` and then :py:meth:`~nativeio.I2C.deinit` the +//| hardware. +//| +//| Here is blinky:: +//| +//| import nativeio +//| from board import * +//| import time +//| +//| with nativeio.DigitalInOut(D13) as led: +//| led.value = True +//| time.sleep(0.1) +//| led.value = False +//| time.sleep(0.1) +//| + +STATIC const mp_rom_map_elem_t nativeio_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_nativeio) }, + { MP_ROM_QSTR(MP_QSTR_AnalogIn), MP_ROM_PTR(&nativeio_analogin_type) }, + { MP_ROM_QSTR(MP_QSTR_AnalogOut), MP_ROM_PTR(&nativeio_analogout_type) }, + { MP_ROM_QSTR(MP_QSTR_DigitalInOut), MP_ROM_PTR(&nativeio_digitalinout_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&nativeio_i2c_type) }, + { MP_ROM_QSTR(MP_QSTR_PWMOut), MP_ROM_PTR(&nativeio_pwmout_type) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&nativeio_spi_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(nativeio_module_globals, nativeio_module_globals_table); + +const mp_obj_module_t nativeio_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&nativeio_module_globals, +}; diff --git a/shared-bindings/nativeio/__init__.h b/shared-bindings/nativeio/__init__.h new file mode 100644 index 0000000000..7f4c01e051 --- /dev/null +++ b/shared-bindings/nativeio/__init__.h @@ -0,0 +1,34 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_SHARED_BINDINGS_NATIVEIO___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO___INIT___H__ + +#include "py/obj.h" + +// Nothing now. + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_NATIVEIO___INIT___H__ diff --git a/shared-bindings/neopixel_write/__init__.c b/shared-bindings/neopixel_write/__init__.c new file mode 100644 index 0000000000..73fd803c5b --- /dev/null +++ b/shared-bindings/neopixel_write/__init__.c @@ -0,0 +1,75 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 "py/obj.h" +#include "py/mphal.h" +#include "py/runtime.h" + +#include "common-hal/nativeio/types.h" + +#include "shared-bindings/neopixel_write/__init__.h" + +//| :mod:`neopixel_write` --- Low-level neopixel implementation +//| =========================================================== +//| +//| .. module:: neopixel_write +//| :synopsis: Low-level neopixel implementation +//| :platform: SAMD21 +//| +//| The `neopixel_write` module contains a helper method to write out bytes in +//| the neopixel protocol. + +//| .. method:: neopixel_write.neopixel_write(digitalinout, buf, is800KHz) +//| +//| Write buf out on the given DigitalInOut. +//| +//| :param ~nativeio.DigitalInOut gpio: the DigitalInOut to output with +//| :param bytearray buf: The bytes to clock out. No assumption is made about color order +//| :param bool is800KHz: True if the pixels are 800KHz, otherwise 400KHz is assumed. +//| +STATIC mp_obj_t neopixel_write_neopixel_write_(mp_obj_t digitalinout_obj, mp_obj_t buf, mp_obj_t is800k) { + // Convert parameters into expected types. + const nativeio_digitalinout_obj_t *digitalinout = MP_OBJ_TO_PTR(digitalinout_obj); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); + // Call platform's neopixel write function with provided buffer and options. + common_hal_neopixel_write(digitalinout, (uint8_t*)bufinfo.buf, bufinfo.len, + mp_obj_is_true(is800k)); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(neopixel_write_neopixel_write_obj, neopixel_write_neopixel_write_); + +STATIC const mp_rom_map_elem_t neopixel_write_module_globals_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&neopixel_write_neopixel_write_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(neopixel_write_module_globals, neopixel_write_module_globals_table); + +const mp_obj_module_t neopixel_write_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t*)&neopixel_write_module_globals, +}; diff --git a/shared-bindings/neopixel_write/__init__.h b/shared-bindings/neopixel_write/__init__.h new file mode 100644 index 0000000000..fdf3c38f69 --- /dev/null +++ b/shared-bindings/neopixel_write/__init__.h @@ -0,0 +1,37 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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 SAMD_NEOPIXEL_WRITE_H +#define SAMD_NEOPIXEL_WRITE_H + +#include +#include + +#include "common-hal/nativeio/types.h" + +extern void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* gpio, uint8_t *pixels, uint32_t numBytes, bool is800KHz); + +#endif diff --git a/atmel-samd/modutime.c b/shared-bindings/time/__init__.c similarity index 51% rename from atmel-samd/modutime.c rename to shared-bindings/time/__init__.c index 575066be41..cd41884fd1 100644 --- a/atmel-samd/modutime.c +++ b/shared-bindings/time/__init__.c @@ -5,6 +5,7 @@ * * Copyright (c) 2013, 2014 Damien P. George * Copyright (c) 2015 Josef Gajdusek + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,71 +26,66 @@ * THE SOFTWARE. */ -#include #include -#include "py/nlr.h" +//#include "py/nlr.h" #include "py/obj.h" -#include "py/gc.h" -#include "py/runtime.h" -#include "py/mphal.h" -#include "py/smallint.h" +//#include "py/gc.h" +//#include "py/runtime.h" +//#include "py/mphal.h" +//#include "py/smallint.h" +#include "shared-bindings/time/__init__.h" -/// \module time - time related functions -/// -/// The `time` module provides functions for getting the current time and date, -/// and for sleeping. +//| :mod:`time` --- time and timing related functions +//| ======================================================== +//| +//| .. module:: time +//| :synopsis: time and timing related functions +//| :platform: SAMD21 +//| +//| The `time` module is a strict subset of the CPython `time` module. So, code +//| written in MicroPython will work in CPython but not necessarily the other +//| way around. +//| +//| .. method:: monotonic() +//| +//| Returns an always increasing value of time with an unknown reference +//| point. Only use it to compare against other values from `monotonic`. +//| +//| :return: the current monotonic time +//| :rtype: float +//| +STATIC mp_obj_t time_monotonic(void) { + return mp_obj_new_float(common_hal_time_monotonic() / 100.0); +} +MP_DEFINE_CONST_FUN_OBJ_0(time_monotonic_obj, time_monotonic); -/// \function sleep(seconds) -/// Sleep for the given number of seconds. +//| .. method:: sleep(seconds) +//| +//| Sleep for a given number of seconds. +//| +//| :param float seconds: the time to sleep in fractional seconds +//| STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { #if MICROPY_PY_BUILTINS_FLOAT - mp_hal_delay_ms(1000 * mp_obj_get_float(seconds_o)); + common_hal_time_delay_ms(1000 * mp_obj_get_float(seconds_o)); #else - mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o)); + common_hal_time_delay_ms(1000 * mp_obj_get_int(seconds_o)); #endif return mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep); -STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) { - mp_hal_delay_ms(mp_obj_get_int(arg)); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_ms_obj, time_sleep_ms); - -STATIC mp_obj_t time_sleep_us(mp_obj_t arg) { - mp_hal_delay_us(mp_obj_get_int(arg)); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_us_obj, time_sleep_us); - -STATIC mp_obj_t time_ticks_ms(void) { - return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_ms_obj, time_ticks_ms); - -STATIC mp_obj_t time_ticks_diff(mp_obj_t start_in, mp_obj_t end_in) { - // we assume that the arguments come from ticks_xx so are small ints - uint32_t start = MP_OBJ_SMALL_INT_VALUE(start_in); - uint32_t end = MP_OBJ_SMALL_INT_VALUE(end_in); - return MP_OBJ_NEW_SMALL_INT((end - start) & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(time_ticks_diff_obj, time_ticks_diff); - STATIC const mp_map_elem_t time_module_globals_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) }, + { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_time) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_monotonic), (mp_obj_t)&time_monotonic_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&time_sleep_ms_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&time_sleep_us_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&time_ticks_ms_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&time_ticks_diff_obj }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); -const mp_obj_module_t utime_module = { +const mp_obj_module_t time_module = { .base = { &mp_type_module }, .globals = (mp_obj_dict_t*)&time_module_globals, }; diff --git a/shared-bindings/time/__init__.h b/shared-bindings/time/__init__.h new file mode 100644 index 0000000000..37bd26a4df --- /dev/null +++ b/shared-bindings/time/__init__.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * + * 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_SHARED_BINDINGS_TIME___INIT___H__ +#define __MICROPY_INCLUDED_SHARED_BINDINGS_TIME___INIT___H__ + +#include +#include + +extern uint64_t common_hal_time_monotonic(void); +extern void common_hal_time_delay_ms(uint32_t); + +#endif // __MICROPY_INCLUDED_SHARED_BINDINGS_TIME___INIT___H__ diff --git a/shared-module/bitbangio/I2C.c b/shared-module/bitbangio/I2C.c new file mode 100644 index 0000000000..bab5074b40 --- /dev/null +++ b/shared-module/bitbangio/I2C.c @@ -0,0 +1,210 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George, Scott Shawcroft + * + * 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 "shared-bindings/bitbangio/I2C.h" + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/nativeio/DigitalInOut.h" +#include "shared-module/bitbangio/types.h" + +#define I2C_STRETCH_LIMIT 255 + +STATIC void delay(bitbangio_i2c_obj_t *self) { + // We need to use an accurate delay to get acceptable I2C + // speeds (eg 1us should be not much more than 1us). + common_hal_mcu_delay_us(self->us_delay); +} + +STATIC void scl_low(bitbangio_i2c_obj_t *self) { + common_hal_nativeio_digitalinout_set_value(&self->scl, false); +} + +STATIC void scl_release(bitbangio_i2c_obj_t *self) { + common_hal_nativeio_digitalinout_set_value(&self->scl, true); + delay(self); + // For clock stretching, wait for the SCL pin to be released, with timeout. + for (int count = I2C_STRETCH_LIMIT; !common_hal_nativeio_digitalinout_get_value(&self->scl) && count; --count) { + common_hal_mcu_delay_us(1); + } +} + +STATIC void sda_low(bitbangio_i2c_obj_t *self) { + common_hal_nativeio_digitalinout_set_value(&self->sda, false); +} + +STATIC void sda_release(bitbangio_i2c_obj_t *self) { + common_hal_nativeio_digitalinout_set_value(&self->sda, true); +} + +STATIC bool sda_read(bitbangio_i2c_obj_t *self) { + common_hal_nativeio_digitalinout_switch_to_input(&self->sda, PULL_UP); + bool value = common_hal_nativeio_digitalinout_get_value(&self->sda); + common_hal_nativeio_digitalinout_switch_to_output(&self->sda, true, DRIVE_MODE_OPEN_DRAIN); + return value; +} + +STATIC void start(bitbangio_i2c_obj_t *self) { + sda_release(self); + delay(self); + scl_release(self); + sda_low(self); + delay(self); +} + +STATIC void stop(bitbangio_i2c_obj_t *self) { + delay(self); + sda_low(self); + delay(self); + scl_release(self); + sda_release(self); + delay(self); +} + +STATIC int write_byte(bitbangio_i2c_obj_t *self, uint8_t val) { + delay(self); + scl_low(self); + + for (int i = 7; i >= 0; i--) { + if ((val >> i) & 1) { + sda_release(self); + } else { + sda_low(self); + } + delay(self); + scl_release(self); + scl_low(self); + } + + sda_release(self); + delay(self); + scl_release(self); + + int ret = sda_read(self); + delay(self); + scl_low(self); + + return !ret; +} + +STATIC bool read_byte(bitbangio_i2c_obj_t *self, uint8_t *val, bool ack) { + delay(self); + scl_low(self); + delay(self); + + uint8_t data = 0; + for (int i = 7; i >= 0; i--) { + scl_release(self); + data = (data << 1) | sda_read(self); + scl_low(self); + delay(self); + } + *val = data; + + // send ack/nack bit + if (ack) { + sda_low(self); + } + delay(self); + scl_release(self); + scl_low(self); + sda_release(self); + + return true; +} + +void shared_module_bitbangio_i2c_construct(bitbangio_i2c_obj_t *self, + const mcu_pin_obj_t * scl, + const mcu_pin_obj_t * sda, + uint32_t freq) { + self->us_delay = 500000 / freq; + if (self->us_delay == 0) { + self->us_delay = 1; + } + digitalinout_result_t result = common_hal_nativeio_digitalinout_construct(&self->scl, scl); + if (result != DIGITALINOUT_OK) { + return; + } + result = common_hal_nativeio_digitalinout_construct(&self->sda, sda); + if (result != DIGITALINOUT_OK) { + common_hal_nativeio_digitalinout_deinit(&self->scl); + return; + } + common_hal_nativeio_digitalinout_switch_to_output(&self->scl, true, DRIVE_MODE_OPEN_DRAIN); + common_hal_nativeio_digitalinout_switch_to_output(&self->sda, true, DRIVE_MODE_OPEN_DRAIN); + + stop(self); +} + +void shared_module_bitbangio_i2c_deinit(bitbangio_i2c_obj_t *self) { + common_hal_nativeio_digitalinout_deinit(&self->scl); + common_hal_nativeio_digitalinout_deinit(&self->sda); +} + +bool shared_module_bitbangio_i2c_probe(bitbangio_i2c_obj_t *self, uint8_t addr) { + start(self); + bool ok = write_byte(self, addr << 1); + stop(self); + return ok; +} + +bool shared_module_bitbangio_i2c_write(bitbangio_i2c_obj_t *self, uint16_t addr, + const uint8_t *data, size_t len, bool transmit_stop_bit) { + // start the I2C transaction + start(self); + bool ok = write_byte(self, addr << 1); + + for (uint32_t i = 0; i < len; i++) { + ok = ok && write_byte(self, data[i]); + if (!ok) { + break; + } + } + + if (transmit_stop_bit) { + stop(self); + } + return ok; +} + +bool shared_module_bitbangio_i2c_read(bitbangio_i2c_obj_t *self, uint16_t addr, + uint8_t * data, size_t len) { + // start the I2C transaction + start(self); + bool ok = write_byte(self, (addr << 1) | 1); + + for (uint32_t i = 0; i < len; i++) { + ok = ok && read_byte(self, data + i, i < len - 1); + if (!ok) { + break; + } + } + + stop(self); + return ok; +} diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c new file mode 100644 index 0000000000..5d77efaf97 --- /dev/null +++ b/shared-module/bitbangio/SPI.c @@ -0,0 +1,167 @@ +/* + * This file is part of the MicroPython 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 "mpconfigport.h" + +#include "py/obj.h" + +#include "common-hal/microcontroller/types.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/nativeio/DigitalInOut.h" +#include "shared-module/bitbangio/types.h" + +#define MAX_BAUDRATE (common_hal_mcu_get_clock_frequency() / 48) + +extern void shared_module_bitbangio_spi_construct(bitbangio_spi_obj_t *self, + const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, + const mcu_pin_obj_t * miso, uint32_t baudrate) { + digitalinout_result_t result = common_hal_nativeio_digitalinout_construct(&self->clock, clock); + if (result != DIGITALINOUT_OK) { + return; + } + result = common_hal_nativeio_digitalinout_construct(&self->mosi, mosi); + if (result != DIGITALINOUT_OK) { + common_hal_nativeio_digitalinout_deinit(&self->clock); + return; + } + result = common_hal_nativeio_digitalinout_construct(&self->miso, miso); + if (result != DIGITALINOUT_OK) { + common_hal_nativeio_digitalinout_deinit(&self->clock); + common_hal_nativeio_digitalinout_deinit(&self->mosi); + return; + } + + self->delay_half = 500000 / baudrate; + // round delay_half up so that: actual_baudrate <= requested_baudrate + if (500000 % baudrate != 0) { + self->delay_half += 1; + } + + self->polarity = 0; + self->phase = 0; +} + +extern void shared_module_bitbangio_spi_deinit(bitbangio_spi_obj_t *self) { + common_hal_nativeio_digitalinout_deinit(&self->clock); + common_hal_nativeio_digitalinout_deinit(&self->mosi); + common_hal_nativeio_digitalinout_deinit(&self->miso); +} + +bool shared_module_bitbangio_spi_transfer(bitbangio_spi_obj_t *self, + const uint8_t *write_buffer, size_t write_buffer_len, + uint8_t *read_buffer, size_t read_buffer_len) { + uint32_t delay_half = self->delay_half; + + // only MSB transfer is implemented + + // If a port defines MICROPY_PY_MACHINE_SPI_MIN_DELAY, and the configured + // delay_half is equal to this value, then the software SPI implementation + // will run as fast as possible, limited only by CPU speed and GPIO time. + #ifdef MICROPY_PY_MACHINE_SPI_MIN_DELAY + if (delay_half <= MICROPY_PY_MACHINE_SPI_MIN_DELAY) { + for (size_t i = 0; i < write_buffer_len; ++i) { + uint8_t data_out = write_buffer[i]; + for (int j = 0; j < 8; ++j, data_out <<= 1) { + common_hal_nativeio_digitalinout_set_value(&self->mosi, (data_out >> 7) & 1); + common_hal_nativeio_digitalinout_set_value(&self->clock, 1 - self->polarity); + common_hal_nativeio_digitalinout_set_value(&self->clock, self->polarity); + } + if (dest != NULL) { + dest[i] = data_in; + } + } + + // Clock out zeroes while we read. + common_hal_nativeio_digitalinout_set_value(&self->mosi, false); + for (size_t i = 0; i < read_buffer_len; ++i) { + uint8_t data_in = 0; + for (int j = 0; j < 8; ++j, data_out <<= 1) { + common_hal_nativeio_digitalinout_set_value(&self->clock, 1 - self->polarity); + data_in = (data_in << 1) | common_hal_nativeio_digitalinout_get_value(&self->miso); + common_hal_nativeio_digitalinout_set_value(&self->clock, self->polarity); + } + read_buffer[i] = data_in; + } + return true; + } + #endif + + for (size_t i = 0; i < write_buffer_len; ++i) { + uint8_t data_out = write_buffer[i]; + for (int j = 0; j < 8; ++j, data_out <<= 1) { + common_hal_nativeio_digitalinout_set_value(&self->mosi, (data_out >> 7) & 1); + if (self->phase == 0) { + common_hal_mcu_delay_us(delay_half); + common_hal_nativeio_digitalinout_set_value(&self->clock, 1 - self->polarity); + } else { + common_hal_nativeio_digitalinout_set_value(&self->clock, 1 - self->polarity); + common_hal_mcu_delay_us(delay_half); + } + if (self->phase == 0) { + common_hal_mcu_delay_us(delay_half); + common_hal_nativeio_digitalinout_set_value(&self->clock, self->polarity); + } else { + common_hal_nativeio_digitalinout_set_value(&self->clock, self->polarity); + common_hal_mcu_delay_us(delay_half); + } + } + + // Some ports need a regular callback, but probably we don't need + // to do this every byte, or even at all. + #ifdef MICROPY_EVENT_POLL_HOOK + MICROPY_EVENT_POLL_HOOK; + #endif + } + common_hal_nativeio_digitalinout_set_value(&self->mosi, false); + for (size_t i = 0; i < read_buffer_len; ++i) { + uint8_t data_in = 0; + for (int j = 0; j < 8; ++j) { + if (self->phase == 0) { + common_hal_mcu_delay_us(delay_half); + common_hal_nativeio_digitalinout_set_value(&self->clock, 1 - self->polarity); + } else { + common_hal_nativeio_digitalinout_set_value(&self->clock, 1 - self->polarity); + common_hal_mcu_delay_us(delay_half); + } + data_in = (data_in << 1) | common_hal_nativeio_digitalinout_get_value(&self->miso); + if (self->phase == 0) { + common_hal_mcu_delay_us(delay_half); + common_hal_nativeio_digitalinout_set_value(&self->clock, self->polarity); + } else { + common_hal_nativeio_digitalinout_set_value(&self->clock, self->polarity); + common_hal_mcu_delay_us(delay_half); + } + } + read_buffer[i] = data_in; + + // Some ports need a regular callback, but probably we don't need + // to do this every byte, or even at all. + #ifdef MICROPY_EVENT_POLL_HOOK + MICROPY_EVENT_POLL_HOOK; + #endif + } + return true; +} diff --git a/atmel-samd/modmachine_adc.h b/shared-module/bitbangio/__init__.c similarity index 87% rename from atmel-samd/modmachine_adc.h rename to shared-module/bitbangio/__init__.c index ed01f20c8f..674343c533 100644 --- a/atmel-samd/modmachine_adc.h +++ b/shared-module/bitbangio/__init__.c @@ -1,9 +1,9 @@ /* - * This file is part of the Micro Python project, http://micropython.org/ + * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2016 Scott Shawcroft * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,4 +24,4 @@ * THE SOFTWARE. */ -extern const mp_obj_type_t adc_type; +// Nothing now. diff --git a/shared-module/bitbangio/types.h b/shared-module/bitbangio/types.h new file mode 100644 index 0000000000..e6a29ab54c --- /dev/null +++ b/shared-module/bitbangio/types.h @@ -0,0 +1,51 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * 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_SHARED_MODULE_BITBANGIO_TYPES_H__ +#define __MICROPY_INCLUDED_SHARED_MODULE_BITBANGIO_TYPES_H__ + +#include "common-hal/nativeio/types.h" + +#include "py/obj.h" + +typedef struct { + mp_obj_base_t base; + nativeio_digitalinout_obj_t scl; + nativeio_digitalinout_obj_t sda; + uint32_t us_delay; +} bitbangio_i2c_obj_t; + +typedef struct { + mp_obj_base_t base; + nativeio_digitalinout_obj_t clock; + nativeio_digitalinout_obj_t mosi; + nativeio_digitalinout_obj_t miso; + uint32_t delay_half; + uint8_t polarity; + uint8_t phase; +} bitbangio_spi_obj_t; + +#endif // __MICROPY_INCLUDED_SHARED_MODULE_BITBANGIO_TYPES_H__