diff options
| author | Scott Shawcroft <scott@chickadee.tech> | 2016-11-03 15:50:59 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott.shawcroft@gmail.com> | 2016-11-21 14:11:52 -0800 |
| commit | ccbb5e84f980e252f7380d96fcc5c417a8a64523 (patch) | |
| tree | 743fef26c6176aca6582b92a85829a565e60c414 /atmel-samd | |
| parent | 93218281588b42331d83e4aaa45ac1abe4af130b (diff) | |
This introduces an alternative hardware API called nativeio structured around different functions that are typically accelerated by native hardware. Its not meant to reflect the structure of the hardware.
Docs are here: http://tannewt-micropython.readthedocs.io/en/microcontroller/
It differs from upstream's machine in the following ways:
* Python API is identical across ports due to code structure. (Lives in shared-bindings)
* Focuses on abstracting common functionality (AnalogIn) and not representing structure (ADC).
* Documentation lives with code making it easy to ensure they match.
* Pin is split into references (board.D13 and microcontroller.pin.PA17) and functionality (DigitalInOut).
* All nativeio classes claim underlying hardware resources when inited on construction, support Context Managers (aka with statements) and have deinit methods which release the claimed hardware.
* All constructors take pin references rather than peripheral ids. Its up to the implementation to find hardware or throw and exception.
Diffstat (limited to 'atmel-samd')
60 files changed, 1671 insertions, 2377 deletions
diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index 8f89d83dd..90bde67a5 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 51b8285e7..5719aaa2f 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 4702fe93b..bdd5f9b5e 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 fc778a782..d055b0d0d 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 bb4836af1..b6c2336f7 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 d4367f90f..0834403c6 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 9c656863b..a3a4fef76 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 dd57b5710..d109d6987 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 89fa1620a..5919bb786 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 fa3ffc01a..51ac9da85 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 b482e53f2..8eac1713f 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 89fa1620a..5919bb786 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 b7fc593bd..067f954a8 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 c54359562..d6af74997 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 4b2f31b50..a2f59b361 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 0fb0815d2..baef1f853 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 7c65ec30d..000000000 --- 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_adc.h b/atmel-samd/common-hal/board/__init__.c index ed01f20c8..acab1ac07 100644 --- a/atmel-samd/modmachine_adc.h +++ b/atmel-samd/common-hal/board/__init__.c @@ -24,4 +24,11 @@ * THE SOFTWARE. */ -extern const mp_obj_type_t adc_type; +#include <string.h> + +#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 000000000..2e8b72a2c --- /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 000000000..260e2c1b5 --- /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 index 73150640f..48ef7346b 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; - -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; + 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; -#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 70ca0a67a..000000000 --- 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 000000000..faf63265f --- /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 <string.h> + +#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 000000000..5540cb37d --- /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 <stdint.h> +#include <string.h> + +#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 000000000..119832ff6 --- /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 <stdint.h> +#include <string.h> + +#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 000000000..9eb2361fb --- /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 000000000..a444ba864 --- /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 <stdint.h> + +#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 000000000..7600766f7 --- /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 000000000..e0ec8acfb --- /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 000000000..0842262bd --- /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 <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/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 000000000..f720c4518 --- /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/modmachine_dac.h b/atmel-samd/common-hal/time/__init__.c index 931987cd9..0d60adef2 100644 --- a/atmel-samd/modmachine_dac.h +++ b/atmel-samd/common-hal/time/__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 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 @@ -24,4 +24,16 @@ * THE SOFTWARE. */ -extern const mp_obj_type_t dac_type; +#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 9bf4682eb..642f0222a 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 d59f7b38a..ef0c8be1f 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 1fbe7b298..ac27e274b 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -1,5 +1,4 @@ #include <stdint.h> -#include <stdio.h> #include <string.h> #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,13 +229,74 @@ void start_mp() { pyexec_file("main.py"); } +#ifdef UART_REPL +struct usart_module usart_instance; +#endif + +#ifdef ENABLE_MICRO_TRACE_BUFFER +// Stores 2 ^ TRACE_BUFFER_MAGNITUDE_PACKETS packets. +// 7 -> 128 packets +#define TRACE_BUFFER_MAGNITUDE_PACKETS 7 +// Size in uint32_t. Two per packet. +#define TRACE_BUFFER_SIZE (1 << (TRACE_BUFFER_MAGNITUDE_PACKETS + 1)) +// Size in bytes. 4 bytes per uint32_t. +#define TRACE_BUFFER_SIZE_BYTES (TRACE_BUFFER_SIZE << 2) +__attribute__((__aligned__(TRACE_BUFFER_SIZE_BYTES))) uint32_t mtb[TRACE_BUFFER_SIZE]; +#endif + +// Serial number as hex characters. +char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; +void load_serial_number(void) { + char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', + 'B', 'C', 'D', 'E', 'F'}; + uint32_t* addresses[4] = {(uint32_t *) 0x0080A00C, (uint32_t *) 0x0080A040, + (uint32_t *) 0x0080A044, (uint32_t *) 0x0080A048}; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 8; j++) { + uint8_t nibble = (*(addresses[i]) >> j * 4) & 0xf; + serial_number[i * 8 + j] = nibble_to_hex[nibble]; + } + } +} + +void samd21_init(void) { +#ifdef ENABLE_MICRO_TRACE_BUFFER + REG_MTB_POSITION = ((uint32_t) (mtb - REG_MTB_BASE)) & 0xFFFFFFF8; + REG_MTB_FLOW = (((uint32_t) mtb - REG_MTB_BASE) + TRACE_BUFFER_SIZE_BYTES) & 0xFFFFFFF8; + REG_MTB_MASTER = 0x80000000 + (TRACE_BUFFER_MAGNITUDE_PACKETS - 1); +#endif + + load_serial_number(); + + irq_initialize_vectors(); + cpu_irq_enable(); + + // Initialize the sleep manager + sleepmgr_init(); + + system_init(); + + delay_init(); + + board_init(); + + // Configure millisecond timer initialization. + tick_init(); + + // Uncomment to init PIN_PA17 for debugging. + // struct port_config pin_conf; + // port_get_config_defaults(&pin_conf); + // + // pin_conf.direction = PORT_PIN_DIR_OUTPUT; + // port_pin_set_config(MICROPY_HW_LED1, &pin_conf); + // port_pin_set_output_level(MICROPY_HW_LED1, false); + + neopixel_status_init(); +} + 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 @@ -293,6 +349,7 @@ void gc_collect(void) { // 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(); } @@ -334,80 +391,3 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c __fatal_error("Assertion failed"); } #endif - -#if MICROPY_MIN_USE_SAMD21_MCU - -#ifdef UART_REPL -struct usart_module usart_instance; -#endif - -#ifdef ENABLE_MICRO_TRACE_BUFFER -// Stores 2 ^ TRACE_BUFFER_MAGNITUDE_PACKETS packets. -// 7 -> 128 packets -#define TRACE_BUFFER_MAGNITUDE_PACKETS 7 -// Size in uint32_t. Two per packet. -#define TRACE_BUFFER_SIZE (1 << (TRACE_BUFFER_MAGNITUDE_PACKETS + 1)) -// Size in bytes. 4 bytes per uint32_t. -#define TRACE_BUFFER_SIZE_BYTES (TRACE_BUFFER_SIZE << 2) -__attribute__((__aligned__(TRACE_BUFFER_SIZE_BYTES))) uint32_t mtb[TRACE_BUFFER_SIZE]; -#endif - -// Serial number as hex characters. -char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH]; -void load_serial_number(void) { - char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', - 'B', 'C', 'D', 'E', 'F'}; - uint32_t* addresses[4] = {(uint32_t *) 0x0080A00C, (uint32_t *) 0x0080A040, - (uint32_t *) 0x0080A044, (uint32_t *) 0x0080A048}; - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 8; j++) { - uint8_t nibble = (*(addresses[i]) >> j * 4) & 0xf; - serial_number[i * 8 + j] = nibble_to_hex[nibble]; - } - } -} - -void samd21_init(void) { -#ifdef ENABLE_MICRO_TRACE_BUFFER - REG_MTB_POSITION = ((uint32_t) (mtb - REG_MTB_BASE)) & 0xFFFFFFF8; - REG_MTB_FLOW = (((uint32_t) mtb - REG_MTB_BASE) + TRACE_BUFFER_SIZE_BYTES) & 0xFFFFFFF8; - REG_MTB_MASTER = 0x80000000 + (TRACE_BUFFER_MAGNITUDE_PACKETS - 1); -#endif - - load_serial_number(); - - irq_initialize_vectors(); - cpu_irq_enable(); - - // Initialize the sleep manager - sleepmgr_init(); - - system_init(); - - delay_init(); - - board_init(); - - // Configure millisecond timer initialization. - tick_init(); - - // Uncomment to init PIN_PA17 for debugging. - // struct port_config pin_conf; - // port_get_config_defaults(&pin_conf); - // - // pin_conf.direction = PORT_PIN_DIR_OUTPUT; - // port_pin_set_config(MICROPY_HW_LED1, &pin_conf); - // port_pin_set_output_level(MICROPY_HW_LED1, false); - - - #ifdef MICROPY_HW_NEOPIXEL - struct port_config pin_conf; - port_get_config_defaults(&pin_conf); - - 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); - #endif -} - -#endif diff --git a/atmel-samd/modmachine.c b/atmel-samd/modmachine.c deleted file mode 100644 index 791e09ada..000000000 --- a/atmel-samd/modmachine.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013-2015 Damien P. George - * Copyright (c) 2016 Paul Sokolovsky - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <stdint.h> -#include <stdio.h> - -#include "py/obj.h" -#include "py/runtime.h" - -#include "shared-bindings/modules/machine.h" - -#include "modmachine_adc.h" -#include "modmachine_dac.h" -#include "modmachine_pin.h" -#include "modmachine_pwm.h" - -#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 = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&machine_module_globals, -}; - -#endif // MICROPY_PY_MACHINE diff --git a/atmel-samd/modmachine_adc.c b/atmel-samd/modmachine_adc.c deleted file mode 100644 index ac5e6a6f6..000000000 --- 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 <stdio.h> -#include <string.h> - -#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, "<ADC on "); - mp_obj_print_helper(print, self->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 b69fd44dc..000000000 --- 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 <stdio.h> -#include <stdint.h> -#include <string.h> - -#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 14c809057..000000000 --- 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 <stdio.h> -#include <stdint.h> -#include <string.h> - -#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 71adf46a7..000000000 --- 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/<board>/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 214210f50..000000000 --- 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 <stdio.h> -#include <stdint.h> - -#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/modmachine_pwm.h b/atmel-samd/modmachine_pwm.h deleted file mode 100644 index 1989b6e52..000000000 --- a/atmel-samd/modmachine_pwm.h +++ /dev/null @@ -1,27 +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. - */ - -extern const mp_obj_type_t pwm_type; diff --git a/atmel-samd/modneopixel_write.c b/atmel-samd/modneopixel_write.c deleted file mode 100644 index 024e4b1c5..000000000 --- a/atmel-samd/modneopixel_write.c +++ /dev/null @@ -1,34 +0,0 @@ -#include <stdio.h> - -#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 d8cb9d8e4..33bf7acaf 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/modutime.c b/atmel-samd/modutime.c deleted file mode 100644 index 575066be4..000000000 --- a/atmel-samd/modutime.c +++ /dev/null @@ -1,95 +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 - * Copyright (c) 2015 Josef Gajdusek - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <stdio.h> -#include <string.h> - -#include "py/nlr.h" -#include "py/obj.h" -#include "py/gc.h" -#include "py/runtime.h" -#include "py/mphal.h" -#include "py/smallint.h" - -/// \module time - time related functions -/// -/// The `time` module provides functions for getting the current time and date, -/// and for sleeping. - -/// \function sleep(seconds) -/// Sleep for the given number of 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)); - #else - mp_hal_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_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 = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&time_module_globals, -}; diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h index ab78cc8dc..225992c51 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 01a964753..b7887925a 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 858d62813..6df09f9c7 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 000000000..86dd2cb28 --- /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 000000000..a09fd7b91 --- /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 <stdint.h> +#include <stdbool.h> + +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 2ffce5234..000000000 --- a/atmel-samd/pin_defs_samd.c +++ /dev/null @@ -1,57 +0,0 @@ -#include <stdint.h> -#include "pin.h" - -// Returns the pin mode. This value returned by this macro should be one of: -// GPIO_MODE_INPUT, GPIO_MODE_OUTPUT_PP, GPIO_MODE_OUTPUT_OD, -// GPIO_MODE_AF_PP, GPIO_MODE_AF_OD, or GPIO_MODE_ANALOG. - -uint32_t pin_get_mode(const pin_obj_t *pin) { - if (pin->gpio == NULL) { - // Analog only pin - return GPIO_MODE_ANALOG; - } - volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin); - uint32_t pcr = *port_pcr; - uint32_t af = (pcr & PORT_PCR_MUX_MASK) >> 8; - if (af == 0) { - return GPIO_MODE_ANALOG; - } - if (af == 1) { - if (pin->gpio->PDDR & (1 << pin->pin)) { - if (pcr & PORT_PCR_ODE) { - return GPIO_MODE_OUTPUT_OD; - } - return GPIO_MODE_OUTPUT_PP; - } - return GPIO_MODE_INPUT; - } - - if (pcr & PORT_PCR_ODE) { - return GPIO_MODE_AF_OD; - } - return GPIO_MODE_AF_PP; -} - -// Returns the pin pullup/pulldown. The value returned by this macro should -// be one of GPIO_NOPULL, GPIO_PULLUP, or GPIO_PULLDOWN. - -uint32_t pin_get_pull(const pin_obj_t *pin) { - if (pin->gpio == NULL) { - // Analog only pin - return GPIO_NOPULL; - } - volatile uint32_t *port_pcr = GPIO_PIN_TO_PORT_PCR(pin->gpio, pin->pin); - - uint32_t pcr = *port_pcr; - uint32_t af = (pcr & PORT_PCR_MUX_MASK) >> 8; - - // pull is only valid for digital modes (hence the af > 0 test) - - if (af > 0 && (pcr & PORT_PCR_PE) != 0) { - if (pcr & PORT_PCR_PS) { - return GPIO_PULLUP; - } - return GPIO_PULLDOWN; - } - return GPIO_NOPULL; -} diff --git a/atmel-samd/pin_named_pins.c b/atmel-samd/pin_named_pins.c deleted file mode 100644 index 24406f190..000000000 --- a/atmel-samd/pin_named_pins.c +++ /dev/null @@ -1,60 +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 <stdio.h> -#include <string.h> - -#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, "<Pin.%q>", self->name); -} - -const mp_obj_type_t pin_cpu_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_cpu, - .print = pin_named_pins_obj_print, - .locals_dict = (mp_obj_t)&pin_cpu_pins_locals_dict, -}; - -const mp_obj_type_t pin_board_pins_obj_type = { - { &mp_type_type }, - .name = MP_QSTR_board, - .print = pin_named_pins_obj_print, - .locals_dict = (mp_obj_t)&pin_board_pins_locals_dict, -}; - -const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) { - mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins); - mp_map_elem_t *named_elem = mp_map_lookup(named_map, name, MP_MAP_LOOKUP); - if (named_elem != NULL && named_elem->value != NULL) { - return named_elem->value; - } - return NULL; -} diff --git a/atmel-samd/boards/samd21_pins.c b/atmel-samd/samd21_pins.c index c86d7df1f..7298bee85 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/<board>/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 000000000..e2fd57a73 --- /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 684188c1b..000000000 --- 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 0ebc08048..000000000 --- a/atmel-samd/samdneopixel.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef SAMD_NEOPIXEL_WRITE_H -#define SAMD_NEOPIXEL_WRITE_H - -#include <stdint.h> -#include <stdbool.h> - -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 6816757b4..332aee4f5 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 8688928b4..f53fa4d11 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 bcbfcc059..cad69f080 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 731a69146..68e099ba0 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__ |
