Merge pull request #50 from tannewt/microcontroller
Introduce shared APIs: nativeio, microcontroller and board modules. These are the only hardware API on the atmel-samd port.
This commit is contained in:
commit
3b1109c47b
@ -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))
|
||||
|
@ -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__
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -7,3 +7,5 @@
|
||||
#define MICROPY_HW_MCU_NAME "samd21g18"
|
||||
|
||||
#define AUTORESET_DELAY_MS 500
|
||||
|
||||
#define FLASH_INCLUDE "internal_flash.h"
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -7,3 +7,5 @@
|
||||
#define MICROPY_HW_MCU_NAME "samd21g18"
|
||||
|
||||
#define AUTORESET_DELAY_MS 500
|
||||
|
||||
#define FLASH_INCLUDE "internal_flash.h"
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -19,3 +19,5 @@
|
||||
#define SPI_FLASH_SERCOM SERCOM4
|
||||
|
||||
#define AUTORESET_DELAY_MS 500
|
||||
|
||||
#define FLASH_INCLUDE "spi_flash.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
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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__
|
@ -24,4 +24,11 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
extern const mp_obj_type_t dac_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.
|
1
atmel-samd/common-hal/microcontroller/Pin.c
Normal file
1
atmel-samd/common-hal/microcontroller/Pin.c
Normal file
@ -0,0 +1 @@
|
||||
// Pins have no behavior.
|
197
atmel-samd/common-hal/microcontroller/__init__.c
Normal file
197
atmel-samd/common-hal/microcontroller/__init__.c
Normal file
@ -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);
|
@ -24,25 +24,18 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// Machine is the HAL for low-level, hardware accelerated functions. It is not
|
||||
// meant to simplify APIs, its only meant to unify them so that other modules
|
||||
// do not require port specific logic.
|
||||
//
|
||||
// This file defines core data structures for machine classes. They are port
|
||||
// specific and passed through the Python layer untouched.
|
||||
|
||||
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_API_MACHINE_TYPES_H__
|
||||
#define __MICROPY_INCLUDED_ATMEL_SAMD_API_MACHINE_TYPES_H__
|
||||
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__
|
||||
#define __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__
|
||||
|
||||
// Don't reorder these includes because they are dependencies of adc_feature.h.
|
||||
// They should really be included by adc_feature.h.
|
||||
#include "compiler.h"
|
||||
#include "asf/sam0/drivers/system/clock/gclk.h"
|
||||
#include "asf/sam0/utils/cmsis/samd21/include/component/adc.h"
|
||||
#include "asf/sam0/drivers/adc/adc_sam_d_r/adc_feature.h"
|
||||
#include "asf/sam0/drivers/adc/adc_sam_d_r/adc_feature.h" // for adc_positive_input
|
||||
|
||||
#include "asf/sam0/drivers/sercom/i2c/i2c_master.h"
|
||||
#include "asf/sam0/drivers/sercom/spi/spi.h"
|
||||
#include "asf/sam0/drivers/tc/tc.h"
|
||||
#include "asf/sam0/drivers/tcc/tcc.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
@ -63,24 +56,14 @@ typedef struct {
|
||||
|
||||
#define NUM_SERCOMS_PER_PIN 2
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
qstr name;
|
||||
uint32_t pin;
|
||||
bool has_adc;
|
||||
enum adc_positive_input adc_input;
|
||||
pin_timer_t primary_timer;
|
||||
pin_timer_t secondary_timer;
|
||||
pin_sercom_t sercom[NUM_SERCOMS_PER_PIN];
|
||||
} pin_obj_t;
|
||||
mp_obj_base_t base;
|
||||
qstr name;
|
||||
uint32_t pin;
|
||||
bool has_adc;
|
||||
enum adc_positive_input adc_input;
|
||||
pin_timer_t primary_timer;
|
||||
pin_timer_t secondary_timer;
|
||||
pin_sercom_t sercom[NUM_SERCOMS_PER_PIN];
|
||||
} mcu_pin_obj_t;
|
||||
|
||||
typedef struct _machine_i2c_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct i2c_master_module i2c_master_instance;
|
||||
} machine_i2c_obj_t;
|
||||
|
||||
typedef struct _machine_spi_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct spi_module spi_master_instance;
|
||||
} machine_spi_obj_t;
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_API_MACHINE_TYPES_H__
|
||||
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__
|
@ -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"));
|
||||
}
|
||||
}
|
76
atmel-samd/common-hal/nativeio/AnalogIn.c
Normal file
76
atmel-samd/common-hal/nativeio/AnalogIn.c
Normal file
@ -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;
|
||||
}
|
69
atmel-samd/common-hal/nativeio/AnalogOut.c
Normal file
69
atmel-samd/common-hal/nativeio/AnalogOut.c
Normal file
@ -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);
|
||||
}
|
186
atmel-samd/common-hal/nativeio/DigitalInOut.c
Normal file
186
atmel-samd/common-hal/nativeio/DigitalInOut.c
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
159
atmel-samd/common-hal/nativeio/I2C.c
Normal file
159
atmel-samd/common-hal/nativeio/I2C.c
Normal file
@ -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;
|
||||
}
|
114
atmel-samd/common-hal/nativeio/PWMOut.c
Normal file
114
atmel-samd/common-hal/nativeio/PWMOut.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
143
atmel-samd/common-hal/nativeio/SPI.c
Normal file
143
atmel-samd/common-hal/nativeio/SPI.c
Normal file
@ -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;
|
||||
}
|
1
atmel-samd/common-hal/nativeio/__init__.c
Normal file
1
atmel-samd/common-hal/nativeio/__init__.c
Normal file
@ -0,0 +1 @@
|
||||
// No nativeio module functions.
|
86
atmel-samd/common-hal/nativeio/types.h
Normal file
86
atmel-samd/common-hal/nativeio/types.h
Normal file
@ -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__
|
116
atmel-samd/common-hal/neopixel_write/__init__.c
Normal file
116
atmel-samd/common-hal/neopixel_write/__init__.c
Normal file
@ -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);
|
||||
}
|
39
atmel-samd/common-hal/time/__init__.c
Normal file
39
atmel-samd/common-hal/time/__init__.c
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
|
||||
#include "tick.h"
|
||||
|
||||
inline uint64_t common_hal_time_monotonic() {
|
||||
return ticks_ms;
|
||||
}
|
||||
|
||||
void common_hal_time_delay_ms(uint32_t delay) {
|
||||
mp_hal_delay_ms(delay);
|
||||
}
|
@ -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
|
||||
//
|
||||
|
@ -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;
|
||||
|
@ -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,109 +229,6 @@ void start_mp() {
|
||||
pyexec_file("main.py");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// initialise the cpu and peripherals
|
||||
#if MICROPY_MIN_USE_SAMD21_MCU
|
||||
void samd21_init(void);
|
||||
samd21_init();
|
||||
#endif
|
||||
|
||||
|
||||
int stack_dummy;
|
||||
// Store the location of stack_dummy as an approximation for the top of the
|
||||
// stack so the GC can account for objects that may be referenced by the
|
||||
// stack between here and where gc_collect is called.
|
||||
stack_top = (char*)&stack_dummy;
|
||||
reset_mp();
|
||||
|
||||
// Initialise the local flash filesystem after the gc in case we need to
|
||||
// grab memory from it. Create it if needed, mount in on /flash, and set it
|
||||
// as current dir.
|
||||
init_flash_fs();
|
||||
|
||||
// Start USB after getting everything going.
|
||||
#ifdef USB_REPL
|
||||
udc_start();
|
||||
#endif
|
||||
|
||||
// Run boot and main.
|
||||
start_mp();
|
||||
|
||||
// Main script is finished, so now go into REPL mode.
|
||||
// The REPL mode can change, or it can request a soft reset.
|
||||
int exit_code = 0;
|
||||
for (;;) {
|
||||
new_status_color(0x3f, 0x3f, 0x3f);
|
||||
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
|
||||
exit_code = pyexec_raw_repl();
|
||||
} else {
|
||||
exit_code = pyexec_friendly_repl();
|
||||
}
|
||||
if (exit_code == PYEXEC_FORCED_EXIT) {
|
||||
mp_hal_stdout_tx_str("soft reboot\r\n");
|
||||
reset_samd21();
|
||||
reset_mp();
|
||||
start_mp();
|
||||
} else if (exit_code != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
mp_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gc_collect(void) {
|
||||
// WARNING: This gc_collect implementation doesn't try to get root
|
||||
// pointers from CPU registers, and thus may function incorrectly.
|
||||
void *dummy;
|
||||
gc_collect_start();
|
||||
// This naively collects all object references from an approximate stack
|
||||
// range.
|
||||
gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t));
|
||||
gc_collect_end();
|
||||
gc_dump_info();
|
||||
}
|
||||
|
||||
mp_lexer_t *fat_vfs_lexer_new_from_file(const char *filename);
|
||||
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
|
||||
#if MICROPY_VFS_FAT
|
||||
return fat_vfs_lexer_new_from_file(filename);
|
||||
#else
|
||||
(void)filename;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
mp_import_stat_t fat_vfs_import_stat(const char *path);
|
||||
mp_import_stat_t mp_import_stat(const char *path) {
|
||||
#if MICROPY_VFS_FAT
|
||||
return fat_vfs_import_stat(path);
|
||||
#else
|
||||
(void)path;
|
||||
return MP_IMPORT_STAT_NO_EXIST;
|
||||
#endif
|
||||
}
|
||||
|
||||
void mp_keyboard_interrupt(void) {
|
||||
MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(mp_kbd_exception);
|
||||
}
|
||||
|
||||
void nlr_jump_fail(void *val) {
|
||||
}
|
||||
|
||||
void NORETURN __fatal_error(const char *msg) {
|
||||
while (1);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
|
||||
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
|
||||
__fatal_error("Assertion failed");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if MICROPY_MIN_USE_SAMD21_MCU
|
||||
|
||||
#ifdef UART_REPL
|
||||
struct usart_module usart_instance;
|
||||
#endif
|
||||
@ -399,15 +291,103 @@ void samd21_init(void) {
|
||||
// port_pin_set_config(MICROPY_HW_LED1, &pin_conf);
|
||||
// port_pin_set_output_level(MICROPY_HW_LED1, false);
|
||||
|
||||
neopixel_status_init();
|
||||
}
|
||||
|
||||
#ifdef MICROPY_HW_NEOPIXEL
|
||||
struct port_config pin_conf;
|
||||
port_get_config_defaults(&pin_conf);
|
||||
int main(int argc, char **argv) {
|
||||
// initialise the cpu and peripherals
|
||||
samd21_init();
|
||||
|
||||
pin_conf.direction = PORT_PIN_DIR_OUTPUT;
|
||||
port_pin_set_config(MICROPY_HW_NEOPIXEL, &pin_conf);
|
||||
port_pin_set_output_level(MICROPY_HW_NEOPIXEL, false);
|
||||
int stack_dummy;
|
||||
// Store the location of stack_dummy as an approximation for the top of the
|
||||
// stack so the GC can account for objects that may be referenced by the
|
||||
// stack between here and where gc_collect is called.
|
||||
stack_top = (char*)&stack_dummy;
|
||||
reset_mp();
|
||||
|
||||
// Initialise the local flash filesystem after the gc in case we need to
|
||||
// grab memory from it. Create it if needed, mount in on /flash, and set it
|
||||
// as current dir.
|
||||
init_flash_fs();
|
||||
|
||||
// Start USB after getting everything going.
|
||||
#ifdef USB_REPL
|
||||
udc_start();
|
||||
#endif
|
||||
|
||||
// Run boot and main.
|
||||
start_mp();
|
||||
|
||||
// Main script is finished, so now go into REPL mode.
|
||||
// The REPL mode can change, or it can request a soft reset.
|
||||
int exit_code = 0;
|
||||
for (;;) {
|
||||
new_status_color(0x3f, 0x3f, 0x3f);
|
||||
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
|
||||
exit_code = pyexec_raw_repl();
|
||||
} else {
|
||||
exit_code = pyexec_friendly_repl();
|
||||
}
|
||||
if (exit_code == PYEXEC_FORCED_EXIT) {
|
||||
mp_hal_stdout_tx_str("soft reboot\r\n");
|
||||
reset_samd21();
|
||||
reset_mp();
|
||||
start_mp();
|
||||
} else if (exit_code != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
mp_deinit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gc_collect(void) {
|
||||
// WARNING: This gc_collect implementation doesn't try to get root
|
||||
// pointers from CPU registers, and thus may function incorrectly.
|
||||
void *dummy;
|
||||
gc_collect_start();
|
||||
// This naively collects all object references from an approximate stack
|
||||
// range.
|
||||
gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t));
|
||||
mark_flash_cache_for_gc();
|
||||
gc_collect_end();
|
||||
gc_dump_info();
|
||||
}
|
||||
|
||||
mp_lexer_t *fat_vfs_lexer_new_from_file(const char *filename);
|
||||
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
|
||||
#if MICROPY_VFS_FAT
|
||||
return fat_vfs_lexer_new_from_file(filename);
|
||||
#else
|
||||
(void)filename;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
mp_import_stat_t fat_vfs_import_stat(const char *path);
|
||||
mp_import_stat_t mp_import_stat(const char *path) {
|
||||
#if MICROPY_VFS_FAT
|
||||
return fat_vfs_import_stat(path);
|
||||
#else
|
||||
(void)path;
|
||||
return MP_IMPORT_STAT_NO_EXIST;
|
||||
#endif
|
||||
}
|
||||
|
||||
void mp_keyboard_interrupt(void) {
|
||||
MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(mp_kbd_exception);
|
||||
}
|
||||
|
||||
void nlr_jump_fail(void *val) {
|
||||
}
|
||||
|
||||
void NORETURN __fatal_error(const char *msg) {
|
||||
while (1);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
|
||||
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
|
||||
__fatal_error("Assertion failed");
|
||||
}
|
||||
#endif
|
||||
|
@ -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,
|
||||
};
|
@ -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,
|
||||
};
|
@ -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,
|
||||
};
|
@ -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__
|
@ -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,
|
||||
};
|
@ -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,
|
||||
};
|
@ -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 },
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
43
atmel-samd/neopixel_status.c
Normal file
43
atmel-samd/neopixel_status.c
Normal file
@ -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
|
||||
}
|
12
atmel-samd/neopixel_status.h
Normal file
12
atmel-samd/neopixel_status.h
Normal file
@ -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
|
@ -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;
|
||||
}
|
@ -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);
|
166
atmel-samd/samd21_pins.h
Normal file
166
atmel-samd/samd21_pins.h
Normal file
@ -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__
|
@ -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);
|
||||
}
|
@ -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
|
@ -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
|
||||
//
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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__
|
||||
|
2
conf.py
2
conf.py
@ -87,7 +87,7 @@ exclude_patterns = ["*/build-*", "atmel-samd/asf", "atmel-samd/**.c", "atmel-sam
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
#default_role = None
|
||||
default_role = "any"
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
#add_function_parentheses = True
|
||||
|
70
docs/common_hal.md
Normal file
70
docs/common_hal.md
Normal file
@ -0,0 +1,70 @@
|
||||
# Adding `nativeio` support to other ports
|
||||
`nativeio` provides a well-defined, cross-port hardware abstraction layer built to support different devices and their drivers. It's backed by the Common HAL, a C api suitable for supporting different hardware in a similar manner. By sharing this C api, developers can support new hardware easily and cross-port functionality to the new hardware.
|
||||
|
||||
## File layout
|
||||
Common HAL related files are found in these locations:
|
||||
|
||||
* `shared-bindings` Shared home for the Python <-> C bindings which includes inline RST documentation for the created interfaces. The common hal functions are defined in the .h files of the corresponding C files.
|
||||
* `shared-modules` Shared home for C code built on the Common HAL and used by all ports. This code only uses `common_hal` methods defined in `shared-bindings`.
|
||||
* `<port>/common-hal` Port-specific implementation of the Common HAL.
|
||||
|
||||
Each folder has the substructure of <python module name>/<class name> and they should match 1:1. `__init__.c` is used for module globals that are not classes (similar to `__init__.py`).
|
||||
|
||||
## Adding support
|
||||
|
||||
### Modifying the build
|
||||
The first step is to hook the `shared-bindings` into your build for the modules you wish to support. Here's an example of this step for the `atmel-samd/Makefile`:
|
||||
|
||||
```
|
||||
SRC_BINDINGS = \
|
||||
board/__init__.c \
|
||||
microcontroller/__init__.c \
|
||||
microcontroller/Pin.c \
|
||||
nativeio/__init__.c \
|
||||
nativeio/AnalogIn.c \
|
||||
nativeio/AnalogOut.c \
|
||||
nativeio/DigitalInOut.c \
|
||||
nativeio/I2C.c \
|
||||
nativeio/PWMOut.c \
|
||||
nativeio/SPI.c \
|
||||
neopixel_write/__init__.c \
|
||||
time/__init__.c
|
||||
|
||||
SRC_BINDINGS_EXPANDED = $(addprefix shared-bindings/, $(SRC_BINDINGS)) \
|
||||
$(addprefix common-hal/, $(SRC_BINDINGS))
|
||||
|
||||
# Add the resulting objects to the full list
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_BINDINGS_EXPANDED:.c=.o))
|
||||
# Add the sources for QSTR generation
|
||||
SRC_QSTR += $(SRC_C) $(SRC_BINDINGS_EXPANDED) $(STM_SRC_C)
|
||||
```
|
||||
|
||||
The `Makefile` defines the modules to build and adds the sources to include the `shared-bindings` version and the `common-hal` version within the port specific directory. You may comment out certain subfolders to reduce the number of modules to add but don't comment out individual classes. It won't compile then.
|
||||
|
||||
### Hooking the modules in
|
||||
Built in modules are typically defined in `mpconfigport.h`. To add support you should have something like:
|
||||
|
||||
```
|
||||
extern const struct _mp_obj_module_t microcontroller_module;
|
||||
extern const struct _mp_obj_module_t nativeio_module;
|
||||
extern const struct _mp_obj_module_t board_module;
|
||||
extern const struct _mp_obj_module_t time_module;
|
||||
extern const struct _mp_obj_module_t neopixel_write_module;
|
||||
|
||||
#define MICROPY_PORT_BUILTIN_MODULES \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)µcontroller_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_nativeio), (mp_obj_t)&nativeio_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write),(mp_obj_t)&neopixel_write_module } \
|
||||
```
|
||||
|
||||
### Implementing the Common HAL
|
||||
At this point in the port, nothing will compile yet, because there's still work to be done to fix missing sources, compile issues, and link issues. I suggest start with a common-hal directory from another port that implements it such as `atmel-samd` or `esp8266`, deleting the function contents and stubbing out any return statements. Once that is done, you should be able to compile cleanly and import the modules, but nothing will work (though you are getting closer).
|
||||
|
||||
The last step is actually implementing each function in a port specific way. I can't help you with this. :-) If you have any questions how a Common HAL function should work then see the corresponding .h file in `shared-bindings`.
|
||||
|
||||
### Testing
|
||||
Woohoo! You are almost done. After you implement everything, lots of drivers and sample code should just work. There are a number of drivers and examples written for Adafruit's Feather ecosystem. Here are places to start:
|
||||
|
||||
* https://github.com/adafruit?utf8=%E2%9C%93&q=Adafruit_MicroPython&type=&language=
|
@ -8,3 +8,4 @@ the Atmel SAMD21 port
|
||||
:maxdepth: 2
|
||||
|
||||
../atmel-samd/README
|
||||
esp8266/index.rst
|
||||
|
@ -10,6 +10,5 @@ We recommend using `upstream MicroPython <https://micropython.org>`_ for the bel
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
esp8266/index.rst
|
||||
pyboard/index.rst
|
||||
wipy/index.rst
|
||||
|
@ -1,5 +1,15 @@
|
||||
include ../py/mkenv.mk
|
||||
|
||||
# Select the board to build for: if not given on the command line,
|
||||
# then default to PYBV10.
|
||||
BOARD ?= feather_huzzah
|
||||
ifeq ($(wildcard boards/$(BOARD)/.),)
|
||||
$(error Invalid BOARD specified)
|
||||
endif
|
||||
|
||||
# If the build directory is not given, make it reflect the board name.
|
||||
BUILD ?= build-$(BOARD)
|
||||
|
||||
# qstr definitions (must come before including py.mk)
|
||||
QSTR_DEFS = qstrdefsport.h #$(BUILD)/pins_qstr.h
|
||||
|
||||
@ -93,8 +103,34 @@ SRC_C = \
|
||||
fatfs_port.c \
|
||||
axtls_helpers.c \
|
||||
hspi.c \
|
||||
boards/$(BOARD)/pins.c \
|
||||
$(SRC_MOD)
|
||||
|
||||
SRC_COMMON_HAL = \
|
||||
microcontroller/__init__.c \
|
||||
microcontroller/Pin.c \
|
||||
nativeio/__init__.c \
|
||||
nativeio/AnalogIn.c \
|
||||
nativeio/AnalogOut.c \
|
||||
nativeio/DigitalInOut.c \
|
||||
nativeio/I2C.c \
|
||||
nativeio/PWMOut.c \
|
||||
nativeio/SPI.c \
|
||||
neopixel_write/__init__.c \
|
||||
time/__init__.c \
|
||||
board/__init__.c
|
||||
|
||||
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
|
||||
$(addprefix common-hal/, $(SRC_COMMON_HAL))
|
||||
|
||||
SRC_SHARED_MODULE = \
|
||||
bitbangio/__init__.c \
|
||||
bitbangio/I2C.c \
|
||||
bitbangio/SPI.c \
|
||||
|
||||
SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \
|
||||
$(addprefix shared-module/, $(SRC_SHARED_MODULE))
|
||||
|
||||
STM_SRC_C = $(addprefix stmhal/,\
|
||||
pybstdio.c \
|
||||
input.c \
|
||||
@ -149,6 +185,8 @@ OBJ =
|
||||
OBJ += $(PY_O)
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_COMMON_HAL_EXPANDED:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(SRC_SHARED_MODULE_EXPANDED:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(EXTMOD_SRC_C:.c=.o))
|
||||
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
|
||||
@ -156,7 +194,7 @@ OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
|
||||
#OBJ += $(BUILD)/pins_$(BOARD).o
|
||||
|
||||
# List of sources for qstr extraction
|
||||
SRC_QSTR += $(SRC_C) $(STM_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C)
|
||||
SRC_QSTR += $(SRC_C) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED) $(STM_SRC_C) $(EXTMOD_SRC_C) $(DRIVERS_SRC_C)
|
||||
# Append any auto-generated sources that are needed by sources listed in SRC_QSTR
|
||||
SRC_QSTR_AUTO_DEPS +=
|
||||
|
||||
|
48
esp8266/boards/feather_huzzah/pins.c
Normal file
48
esp8266/boards/feather_huzzah/pins.c
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "common-hal/microcontroller/__init__.h"
|
||||
|
||||
STATIC const mp_map_elem_t board_global_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pin_TOUT },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO16), (mp_obj_t)&pin_XPD_DCDC },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO14), (mp_obj_t)&pin_MTMS },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCK), (mp_obj_t)&pin_MTMS },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO12), (mp_obj_t)&pin_MTDI },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MISO), (mp_obj_t)&pin_MTDI },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO13), (mp_obj_t)&pin_MTCK },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MOSI), (mp_obj_t)&pin_MTCK },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO15), (mp_obj_t)&pin_MTDO },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO2), (mp_obj_t)&pin_GPIO2 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO0), (mp_obj_t)&pin_GPIO0 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO4), (mp_obj_t)&pin_GPIO4 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_GPIO4 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RX), (mp_obj_t)&pin_U0RXD },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_TX), (mp_obj_t)&pin_U0TXD },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO5), (mp_obj_t)&pin_DVDD },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_DVDD },
|
||||
};
|
||||
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
|
@ -24,4 +24,11 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
extern const mp_obj_type_t pwm_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/feather_huzzah/pins.c.
|
1
esp8266/common-hal/microcontroller/Pin.c
Normal file
1
esp8266/common-hal/microcontroller/Pin.c
Normal file
@ -0,0 +1 @@
|
||||
// Pins have no behavior.
|
94
esp8266/common-hal/microcontroller/__init__.c
Normal file
94
esp8266/common-hal/microcontroller/__init__.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "common-hal/microcontroller/types.h"
|
||||
#include "shared-bindings/microcontroller/Pin.h"
|
||||
|
||||
#include "eagle_soc.h"
|
||||
#include "osapi.h"
|
||||
#include "etshal.h"
|
||||
|
||||
void common_hal_mcu_delay_us(uint32_t delay) {
|
||||
os_delay_us(delay);
|
||||
}
|
||||
|
||||
// This macro is used to simplify pin definition in boards/<board>/pins.c
|
||||
#define PIN(p_name, p_gpio_number, p_gpio_function, p_peripheral) \
|
||||
const mcu_pin_obj_t pin_## p_name = { \
|
||||
{ &mcu_pin_type }, \
|
||||
.name = MP_QSTR_ ## p_name, \
|
||||
.gpio_number = p_gpio_number, \
|
||||
.gpio_function = p_gpio_function, \
|
||||
.peripheral = p_peripheral, \
|
||||
}
|
||||
|
||||
#define NO_GPIO 0xff
|
||||
#define SPECIAL_CASE 0xfe
|
||||
|
||||
// Using microcontroller names from the datasheet.
|
||||
// https://cdn-shop.adafruit.com/datasheets/ESP8266_Specifications_English.pdf
|
||||
// PIN(mcu name) // function notes | module name | huzzah name
|
||||
PIN(TOUT, NO_GPIO, NO_GPIO, NO_GPIO); // adc | ADC | ADC
|
||||
PIN(XPD_DCDC, 16, SPECIAL_CASE, SPECIAL_CASE); // gpio16 | GPIO16 | GPIO16
|
||||
PIN(MTMS, 14, FUNC_GPIO14, PERIPHS_IO_MUX_MTMS_U); // gpio14 / hspi_clk / pwm2 | GPIO14 | GPIO14/SCK
|
||||
PIN(MTDI, 12, FUNC_GPIO12, PERIPHS_IO_MUX_MTDI_U); // gpio12 / hspi_miso / pwm0 | GPIO12 | GPIO12/MISO
|
||||
PIN(MTCK, 13, FUNC_GPIO13, PERIPHS_IO_MUX_MTCK_U); // gpio13 / hspi_mosi / U0cts | GPIO13 | GPIO13/MOSI
|
||||
PIN(MTDO, 15, FUNC_GPIO15, PERIPHS_IO_MUX_MTDO_U); // gpio15 / hspi_cs / u0rts / pwm1 | GPIO15 | GPIO15
|
||||
PIN(GPIO2, 2, FUNC_GPIO2, PERIPHS_IO_MUX_GPIO2_U); // U1txd | GPIO2 | GPIO2
|
||||
PIN(GPIO0, 0, FUNC_GPIO0, PERIPHS_IO_MUX_GPIO0_U); // spi_Cs2 | GPIO0 | GPIO0
|
||||
PIN(GPIO4, 4, FUNC_GPIO4, PERIPHS_IO_MUX_GPIO4_U); // pwm3 on mcu datasheet as vdd which must be wrong | GPIO4 | GPIO4/SDA
|
||||
PIN(SD_DATA_2, 9, FUNC_GPIO9, PERIPHS_IO_MUX_SD_DATA2_U); // spihd / hspihd / gpio9 | GPIO9
|
||||
PIN(SD_DATA_3, 10, FUNC_GPIO10, PERIPHS_IO_MUX_SD_DATA3_U); // spiwp / hspiwp / gpio10 | GPIO10
|
||||
PIN(SD_CMD, NO_GPIO, NO_GPIO, PERIPHS_IO_MUX_SD_CMD_U); // spi_cs0 / gpio11 | CS0
|
||||
PIN(SD_CLK, NO_GPIO, NO_GPIO, PERIPHS_IO_MUX_SD_CLK_U); // spi_clk / gpio6 | SCLK
|
||||
PIN(SD_DATA_0, NO_GPIO, NO_GPIO, PERIPHS_IO_MUX_SD_DATA0_U); // spi_miso / gpio7 | MISO
|
||||
PIN(SD_DATA_1, NO_GPIO, NO_GPIO, PERIPHS_IO_MUX_SD_DATA1_U); // spi_mosi / gpio8 / u1rxd | MOSI
|
||||
PIN(DVDD, 5, FUNC_GPIO5, PERIPHS_IO_MUX_GPIO5_U); // gpio5 | GPIO5 | GPIO5/SCL
|
||||
PIN(U0RXD, 3, FUNC_GPIO3, PERIPHS_IO_MUX_U0RXD_U); // gpio3 | RXD0 | RXD
|
||||
PIN(U0TXD, 1, FUNC_GPIO1, PERIPHS_IO_MUX_U0TXD_U); // gpio1 / spi_cs1 | TXD0 | TXD
|
||||
|
||||
// This maps MCU pin names to pin objects.
|
||||
STATIC const mp_map_elem_t mcu_pin_global_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_TOUT), (mp_obj_t)&pin_TOUT },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_XPD_DCDC), (mp_obj_t)&pin_XPD_DCDC },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MTMS), (mp_obj_t)&pin_MTMS },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MTDI), (mp_obj_t)&pin_MTDI },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MTCK), (mp_obj_t)&pin_MTCK },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_MTDO), (mp_obj_t)&pin_MTDO },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO2), (mp_obj_t)&pin_GPIO2 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO0), (mp_obj_t)&pin_GPIO0 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_GPIO4), (mp_obj_t)&pin_GPIO4 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD_DATA_2), (mp_obj_t)&pin_SD_DATA_2 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD_DATA_3), (mp_obj_t)&pin_SD_DATA_3 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD_CMD), (mp_obj_t)&pin_SD_CMD },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD_CLK), (mp_obj_t)&pin_SD_CLK },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD_DATA_0), (mp_obj_t)&pin_SD_DATA_0 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SD_DATA_1), (mp_obj_t)&pin_SD_DATA_1 },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_DVDD), (mp_obj_t)&pin_DVDD },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_U0RXD), (mp_obj_t)&pin_U0RXD },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_U0TXD), (mp_obj_t)&pin_U0TXD },
|
||||
};
|
||||
MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table);
|
51
esp8266/common-hal/microcontroller/__init__.h
Normal file
51
esp8266/common-hal/microcontroller/__init__.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MICROPY_INCLUDED_ESP8266_COMMON_HAL_MICROCONTROLLER___INIT___H__
|
||||
#define __MICROPY_INCLUDED_ESP8266_COMMON_HAL_MICROCONTROLLER___INIT___H__
|
||||
|
||||
#include "common-hal/microcontroller/types.h"
|
||||
|
||||
extern const mcu_pin_obj_t pin_TOUT;
|
||||
extern const mcu_pin_obj_t pin_XPD_DCDC;
|
||||
extern const mcu_pin_obj_t pin_MTMS;
|
||||
extern const mcu_pin_obj_t pin_MTDI;
|
||||
extern const mcu_pin_obj_t pin_MTCK;
|
||||
extern const mcu_pin_obj_t pin_MTDO;
|
||||
extern const mcu_pin_obj_t pin_GPIO2;
|
||||
extern const mcu_pin_obj_t pin_GPIO0;
|
||||
extern const mcu_pin_obj_t pin_GPIO4;
|
||||
extern const mcu_pin_obj_t pin_SD_DATA_2;
|
||||
extern const mcu_pin_obj_t pin_SD_DATA_3;
|
||||
extern const mcu_pin_obj_t pin_SD_CMD;
|
||||
extern const mcu_pin_obj_t pin_SD_CLK;
|
||||
extern const mcu_pin_obj_t pin_SD_DATA_0;
|
||||
extern const mcu_pin_obj_t pin_SD_DATA_1;
|
||||
extern const mcu_pin_obj_t pin_DVDD;
|
||||
extern const mcu_pin_obj_t pin_U0RXD;
|
||||
extern const mcu_pin_obj_t pin_U0TXD;
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ESP8266_COMMON_HAL_MICROCONTROLLER___INIT___H__
|
40
esp8266/common-hal/microcontroller/types.h
Normal file
40
esp8266/common-hal/microcontroller/types.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__
|
||||
#define __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
qstr name;
|
||||
uint8_t gpio_number;
|
||||
uint8_t gpio_function;
|
||||
uint32_t peripheral;
|
||||
} mcu_pin_obj_t;
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_TYPES_H__
|
45
esp8266/common-hal/nativeio/AnalogIn.c
Normal file
45
esp8266/common-hal/nativeio/AnalogIn.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#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 "user_interface.h"
|
||||
|
||||
void common_hal_nativeio_analogin_construct(nativeio_analogin_obj_t* self,
|
||||
const mcu_pin_obj_t *pin) {
|
||||
}
|
||||
|
||||
uint16_t common_hal_nativeio_analogin_get_value(nativeio_analogin_obj_t *self) {
|
||||
// ADC is 10 bit so shift by 6 to make it 16-bit.
|
||||
return system_adc_read() << 6;
|
||||
}
|
@ -25,36 +25,23 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.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);
|
||||
#include "shared-bindings/nativeio/AnalogOut.h"
|
||||
|
||||
|
||||
void common_hal_nativeio_analogout_construct(nativeio_analogout_obj_t* self,
|
||||
const mcu_pin_obj_t *pin) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"No hardware support for analog out."));
|
||||
}
|
||||
|
||||
const mp_obj_type_t pin_cpu_pins_obj_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_cpu,
|
||||
.print = pin_named_pins_obj_print,
|
||||
.locals_dict = (mp_obj_t)&pin_cpu_pins_locals_dict,
|
||||
};
|
||||
|
||||
const mp_obj_type_t pin_board_pins_obj_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_board,
|
||||
.print = pin_named_pins_obj_print,
|
||||
.locals_dict = (mp_obj_t)&pin_board_pins_locals_dict,
|
||||
};
|
||||
|
||||
const pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name) {
|
||||
mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)named_pins);
|
||||
mp_map_elem_t *named_elem = mp_map_lookup(named_map, name, MP_MAP_LOOKUP);
|
||||
if (named_elem != NULL && named_elem->value != NULL) {
|
||||
return named_elem->value;
|
||||
}
|
||||
return NULL;
|
||||
void common_hal_nativeio_analogout_deinit(nativeio_analogout_obj_t *self) {
|
||||
}
|
||||
|
||||
void common_hal_nativeio_analogout_set_value(nativeio_analogout_obj_t *self,
|
||||
uint16_t value) {
|
||||
}
|
174
esp8266/common-hal/nativeio/DigitalInOut.c
Normal file
174
esp8266/common-hal/nativeio/DigitalInOut.c
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include "shared-bindings/nativeio/DigitalInOut.h"
|
||||
|
||||
digitalinout_result_t common_hal_nativeio_digitalinout_construct(
|
||||
nativeio_digitalinout_obj_t* self, const mcu_pin_obj_t* pin) {
|
||||
self->pin = pin;
|
||||
PIN_FUNC_SELECT(self->pin->peripheral, self->pin->gpio_function);
|
||||
return DIGITALINOUT_OK;
|
||||
}
|
||||
|
||||
void common_hal_nativeio_digitalinout_deinit(nativeio_digitalinout_obj_t* self) {
|
||||
uint32_t pin_mask = 1 << self->pin->gpio_number;
|
||||
gpio_output_set(0x0, 0x0, 0x0, pin_mask);
|
||||
}
|
||||
|
||||
void common_hal_nativeio_digitalinout_switch_to_input(
|
||||
nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull) {
|
||||
self->output = false;
|
||||
|
||||
if (self->pin->gpio_number == 16) {
|
||||
WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1);
|
||||
WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1);
|
||||
WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1)); // input
|
||||
} else {
|
||||
PIN_PULLUP_DIS(self->pin->peripheral);
|
||||
gpio_output_set(0, 0, 0, 1 << self->pin->gpio_number);
|
||||
}
|
||||
common_hal_nativeio_digitalinout_set_pull(self, pull);
|
||||
}
|
||||
|
||||
void common_hal_nativeio_digitalinout_switch_to_output(
|
||||
nativeio_digitalinout_obj_t* self, bool value,
|
||||
enum digitalinout_drive_mode_t drive_mode) {
|
||||
self->output = true;
|
||||
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
|
||||
if (self->pin->gpio_number == 16) {
|
||||
WRITE_PERI_REG(PAD_XPD_DCDC_CONF, (READ_PERI_REG(PAD_XPD_DCDC_CONF) & 0xffffffbc) | 1);
|
||||
WRITE_PERI_REG(RTC_GPIO_CONF, READ_PERI_REG(RTC_GPIO_CONF) & ~1);
|
||||
WRITE_PERI_REG(RTC_GPIO_ENABLE, (READ_PERI_REG(RTC_GPIO_ENABLE) & ~1) | 1); // output
|
||||
} else if (!self->open_drain) {
|
||||
gpio_output_set(0, 0, 1 << self->pin->gpio_function, 0);
|
||||
PIN_PULLUP_DIS(self->pin->peripheral);
|
||||
}
|
||||
common_hal_nativeio_digitalinout_set_value(self, value);
|
||||
}
|
||||
|
||||
enum digitalinout_direction_t common_hal_nativeio_digitalinout_get_direction(
|
||||
nativeio_digitalinout_obj_t* self) {
|
||||
return self->output? DIRECTION_OUT : DIRECTION_IN;
|
||||
}
|
||||
|
||||
void common_hal_nativeio_digitalinout_set_value(
|
||||
nativeio_digitalinout_obj_t* self, bool value) {
|
||||
if (value) {
|
||||
if (self->open_drain) {
|
||||
// Disable output.
|
||||
gpio_output_set(0, 0, 0, 1 << self->pin->gpio_number);
|
||||
PIN_PULLUP_EN(self->pin->peripheral);
|
||||
} else {
|
||||
// Set high
|
||||
gpio_output_set(1 << self->pin->gpio_number, 0, 0, 0);
|
||||
}
|
||||
} else {
|
||||
if (self->open_drain) {
|
||||
// Enable the output
|
||||
PIN_PULLUP_DIS(self->pin->peripheral);
|
||||
gpio_output_set(0, 0, 1 << self->pin->gpio_number, 0);
|
||||
}
|
||||
// Set low
|
||||
gpio_output_set(0, 1 << self->pin->gpio_number, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Register addresses taken from: https://github.com/esp8266/esp8266-wiki/wiki/gpio-registers
|
||||
volatile uint32_t* PIN_DIR = (uint32_t *) 0x6000030C;
|
||||
volatile uint32_t* PIN_OUT = (uint32_t *) 0x60000300;
|
||||
bool common_hal_nativeio_digitalinout_get_value(
|
||||
nativeio_digitalinout_obj_t* self) {
|
||||
if (!self->output) {
|
||||
if (self->pin->gpio_number == 16) {
|
||||
return READ_PERI_REG(RTC_GPIO_IN_DATA) & 1;
|
||||
}
|
||||
return GPIO_INPUT_GET(self->pin->gpio_number);
|
||||
} else {
|
||||
uint32_t pin_mask = 1 << self->pin->gpio_number;
|
||||
if (self->open_drain && ((*PIN_DIR) & pin_mask) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
return ((*PIN_OUT) & pin_mask) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_nativeio_digitalinout_set_drive_mode(
|
||||
nativeio_digitalinout_obj_t* self,
|
||||
enum digitalinout_drive_mode_t drive_mode) {
|
||||
bool value = common_hal_nativeio_digitalinout_get_value(self);
|
||||
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
|
||||
// True is implemented differently between modes so reset the value to make
|
||||
// sure its correct for the new mode.
|
||||
if (value) {
|
||||
common_hal_nativeio_digitalinout_set_value(self, value);
|
||||
}
|
||||
}
|
||||
|
||||
enum digitalinout_drive_mode_t common_hal_nativeio_digitalinout_get_drive_mode(
|
||||
nativeio_digitalinout_obj_t* self) {
|
||||
if (self->open_drain) {
|
||||
return DRIVE_MODE_OPEN_DRAIN;
|
||||
} else {
|
||||
return DRIVE_MODE_PUSH_PULL;
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_nativeio_digitalinout_set_pull(
|
||||
nativeio_digitalinout_obj_t* self, enum digitalinout_pull_t pull) {
|
||||
if (pull == PULL_DOWN) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"ESP8266 does not support pull down."));
|
||||
return;
|
||||
}
|
||||
if (self->pin->gpio_number == 16) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"Pin does not support pull."));
|
||||
return;
|
||||
}
|
||||
if (pull == PULL_NONE) {
|
||||
PIN_PULLUP_DIS(self->pin->peripheral);
|
||||
} else {
|
||||
PIN_PULLUP_EN(self->pin->peripheral);
|
||||
}
|
||||
}
|
||||
|
||||
enum digitalinout_pull_t common_hal_nativeio_digitalinout_get_pull(
|
||||
nativeio_digitalinout_obj_t* self) {
|
||||
if (self->pin->gpio_number < 16 &&
|
||||
(READ_PERI_REG(self->pin->peripheral) & PERIPHS_IO_MUX_PULLUP) != 0) {
|
||||
return PULL_UP;
|
||||
}
|
||||
return PULL_NONE;
|
||||
}
|
51
esp8266/common-hal/nativeio/I2C.c
Normal file
51
esp8266/common-hal/nativeio/I2C.c
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "shared-bindings/nativeio/I2C.h"
|
||||
#include "py/nlr.h"
|
||||
|
||||
void common_hal_nativeio_i2c_construct(nativeio_i2c_obj_t *self,
|
||||
const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t freq) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"No hardware support for I2C. Use bitbangio instead."));
|
||||
}
|
||||
|
||||
void common_hal_nativeio_i2c_deinit(nativeio_i2c_obj_t *self) {
|
||||
}
|
||||
|
||||
bool common_hal_nativeio_i2c_probe(nativeio_i2c_obj_t *self, uint8_t addr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool common_hal_nativeio_i2c_write(nativeio_i2c_obj_t *self, uint16_t addr,
|
||||
const uint8_t * data, size_t len, bool transmit_stop_bit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool common_hal_nativeio_i2c_read(nativeio_i2c_obj_t *self, uint16_t addr,
|
||||
uint8_t * data, size_t len) {
|
||||
return false;
|
||||
}
|
67
esp8266/common-hal/nativeio/PWMOut.c
Normal file
67
esp8266/common-hal/nativeio/PWMOut.c
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esppwm.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "shared-bindings/nativeio/PWMOut.h"
|
||||
|
||||
// Shared with pybpwm
|
||||
extern bool pwm_inited;
|
||||
|
||||
void common_hal_nativeio_pwmout_construct(nativeio_pwmout_obj_t* self, const mcu_pin_obj_t* pin, uint16_t duty) {
|
||||
// start the PWM subsystem if it's not already running
|
||||
if (!pwm_inited) {
|
||||
pwm_init();
|
||||
pwm_inited = true;
|
||||
}
|
||||
|
||||
self->channel = pwm_add(pin->gpio_number,
|
||||
pin->peripheral,
|
||||
pin->gpio_function);
|
||||
if (self->channel == -1) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError,
|
||||
"PWM not supported on pin %d", pin->gpio_number));
|
||||
}
|
||||
}
|
||||
|
||||
extern void common_hal_nativeio_pwmout_deinit(nativeio_pwmout_obj_t* self) {
|
||||
pwm_delete(self->channel);
|
||||
pwm_start();
|
||||
}
|
||||
|
||||
extern void common_hal_nativeio_pwmout_set_duty_cycle(nativeio_pwmout_obj_t* self, uint16_t duty) {
|
||||
// We get 16 bits of duty in but the underlying code is only ten bit.
|
||||
pwm_set_duty(duty >> 6, self->channel);
|
||||
pwm_start();
|
||||
}
|
||||
|
||||
uint16_t common_hal_nativeio_pwmout_get_duty_cycle(nativeio_pwmout_obj_t* self) {
|
||||
return pwm_get_duty(self->channel) << 6;
|
||||
}
|
90
esp8266/common-hal/nativeio/SPI.c
Normal file
90
esp8266/common-hal/nativeio/SPI.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "esp8266/ets_alt_task.h"
|
||||
#include "esp8266/hspi.h"
|
||||
#include "shared-bindings/nativeio/SPI.h"
|
||||
#include "py/nlr.h"
|
||||
|
||||
#include "eagle_soc.h"
|
||||
|
||||
extern const mcu_pin_obj_t pin_MTMS;
|
||||
extern const mcu_pin_obj_t pin_MTCK;
|
||||
extern const mcu_pin_obj_t pin_MTDI;
|
||||
|
||||
void common_hal_nativeio_spi_construct(nativeio_spi_obj_t *self,
|
||||
const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi,
|
||||
const mcu_pin_obj_t * miso, uint32_t baudrate) {
|
||||
if (clock != &pin_MTMS || mosi != &pin_MTCK || miso != &pin_MTDI) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError,
|
||||
"Pins not valid for SPI"));
|
||||
}
|
||||
}
|
||||
|
||||
void common_hal_nativeio_spi_deinit(nativeio_spi_obj_t *self) {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDI_U, 0);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, 0);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTMS_U, 0);
|
||||
}
|
||||
|
||||
bool common_hal_nativeio_spi_write(nativeio_spi_obj_t *self,
|
||||
const uint8_t * data, size_t len) {
|
||||
size_t chunk_size = 1024;
|
||||
size_t count = len / chunk_size;
|
||||
size_t i = 0;
|
||||
for (size_t j = 0; j < count; ++j) {
|
||||
for (size_t k = 0; k < chunk_size; ++k) {
|
||||
spi_tx8fast(HSPI, data[i]);
|
||||
++i;
|
||||
}
|
||||
ets_loop_iter();
|
||||
}
|
||||
while (i < len) {
|
||||
spi_tx8fast(HSPI, data[i]);
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool common_hal_nativeio_spi_read(nativeio_spi_obj_t *self,
|
||||
uint8_t * data, size_t len) {
|
||||
// Process data in chunks, let the pending tasks run in between
|
||||
size_t chunk_size = 1024; // TODO this should depend on baudrate
|
||||
size_t count = len / chunk_size;
|
||||
size_t i = 0;
|
||||
for (size_t j = 0; j < count; ++j) {
|
||||
for (size_t k = 0; k < chunk_size; ++k) {
|
||||
data[i] = spi_rx8(HSPI);
|
||||
++i;
|
||||
}
|
||||
ets_loop_iter();
|
||||
}
|
||||
while (i < len) {
|
||||
data[i] = spi_rx8(HSPI);
|
||||
++i;
|
||||
}
|
||||
return true;
|
||||
}
|
1
esp8266/common-hal/nativeio/__init__.c
Normal file
1
esp8266/common-hal/nativeio/__init__.c
Normal file
@ -0,0 +1 @@
|
||||
// No nativeio module functions.
|
68
esp8266/common-hal/nativeio/types.h
Normal file
68
esp8266/common-hal/nativeio/types.h
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// This defines the types used to underly the standard nativeio Python objects.
|
||||
// The shared API is defined in terms of these types.
|
||||
|
||||
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__
|
||||
#define __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__
|
||||
|
||||
#include "common-hal/microcontroller/types.h"
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const mcu_pin_obj_t * pin;
|
||||
} nativeio_analogin_obj_t;
|
||||
|
||||
// Not supported, throws error on construction.
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} nativeio_analogout_obj_t;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
const mcu_pin_obj_t * pin;
|
||||
bool output;
|
||||
bool open_drain;
|
||||
} nativeio_digitalinout_obj_t;
|
||||
|
||||
// Not supported, throws error on construction.
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} nativeio_i2c_obj_t;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
} nativeio_spi_obj_t;
|
||||
|
||||
typedef struct {
|
||||
mp_obj_base_t base;
|
||||
int channel;
|
||||
} nativeio_pwmout_obj_t;
|
||||
|
||||
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_NATIVEIO_TYPES_H__
|
33
esp8266/common-hal/neopixel_write/__init__.c
Normal file
33
esp8266/common-hal/neopixel_write/__init__.c
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "shared-bindings/neopixel_write/__init__.h"
|
||||
|
||||
#include "espneopixel.h"
|
||||
|
||||
void common_hal_neopixel_write(const nativeio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes, bool is800KHz) {
|
||||
esp_neopixel_write(digitalinout->pin->gpio_number, pixels, numBytes, is800KHz);
|
||||
}
|
40
esp8266/common-hal/time/__init__.c
Normal file
40
esp8266/common-hal/time/__init__.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include "shared-bindings/time/__init__.h"
|
||||
|
||||
#include "ets_alt_task.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
inline uint64_t common_hal_time_monotonic() {
|
||||
return ((uint64_t)system_time_high_word << 32 | (uint64_t)system_get_time()) / 1000;
|
||||
}
|
||||
|
||||
void common_hal_time_delay_ms(uint32_t delay) {
|
||||
mp_hal_delay_ms(delay);
|
||||
}
|
@ -80,6 +80,9 @@ SECTIONS
|
||||
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
|
||||
|
||||
/* we put some specific text in this section */
|
||||
*common-hal/*.o*(.literal* .text*)
|
||||
*shared-bindings/*.o*(.literal* .text*)
|
||||
*shared-module/*.o*(.literal* .text*)
|
||||
|
||||
*py/argcheck.o*(.literal* .text*)
|
||||
*py/asm*.o*(.literal* .text*)
|
||||
|
@ -1,4 +1,12 @@
|
||||
#ifndef _INCLUDED_ETS_ALT_TASK_H_
|
||||
#define _INCLUDED_ETS_ALT_TASK_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern int ets_loop_iter_disable;
|
||||
extern uint32_t system_time_high_word;
|
||||
|
||||
bool ets_loop_iter(void);
|
||||
|
||||
#endif // _INCLUDED_ETS_ALT_TASK_H_
|
||||
|
@ -40,7 +40,7 @@ typedef struct _pyb_pwm_obj_t {
|
||||
uint8_t channel;
|
||||
} pyb_pwm_obj_t;
|
||||
|
||||
STATIC bool pwm_inited = false;
|
||||
bool pwm_inited = false;
|
||||
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings for PWM
|
||||
|
@ -98,6 +98,7 @@
|
||||
#define MICROPY_ESP8266_APA102 (1)
|
||||
#define MICROPY_ESP8266_NEOPIXEL (1)
|
||||
|
||||
extern void ets_event_poll(void);
|
||||
#define MICROPY_EVENT_POLL_HOOK {ets_event_poll();}
|
||||
#define MICROPY_VM_HOOK_COUNT (10)
|
||||
#define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT;
|
||||
@ -146,6 +147,11 @@ extern const struct _mp_obj_module_t uos_module;
|
||||
extern const struct _mp_obj_module_t mp_module_lwip;
|
||||
extern const struct _mp_obj_module_t mp_module_machine;
|
||||
extern const struct _mp_obj_module_t onewire_module;
|
||||
extern const struct _mp_obj_module_t microcontroller_module;
|
||||
extern const struct _mp_obj_module_t board_module;
|
||||
extern const struct _mp_obj_module_t nativeio_module;
|
||||
extern const struct _mp_obj_module_t bitbangio_module;
|
||||
extern const struct _mp_obj_module_t time_module;
|
||||
|
||||
#define MICROPY_PORT_BUILTIN_MODULES \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_esp), (mp_obj_t)&esp_module }, \
|
||||
@ -157,9 +163,13 @@ extern const struct _mp_obj_module_t onewire_module;
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&uos_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR__onewire), (mp_obj_t)&onewire_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_microcontroller), (mp_obj_t)µcontroller_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&board_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_nativeio), (mp_obj_t)&nativeio_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_module }, \
|
||||
|
||||
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&utime_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_os), (mp_obj_t)&uos_module }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "extmod/modwebsocket.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
|
||||
#if MICROPY_PY_WEBREPL
|
||||
#ifdef MICROPY_PY_WEBREPL
|
||||
|
||||
#if 0 // print debugging info
|
||||
#define DEBUG_printf DEBUG_printf
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "py/objarray.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
#ifdef MICROPY_PY_OS_DUPTERM
|
||||
|
||||
void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
|
||||
mp_obj_t term = MP_STATE_PORT(term_obj);
|
||||
|
@ -11,7 +11,7 @@ educational development boards designed and sold by `Adafruit
|
||||
<https://www.adafruit.com/products/2995>`_.
|
||||
|
||||
Adafruit's MicroPython port features a unified Python APIs available under
|
||||
`shared-bindings` and a growing list of drivers that work with it. Currently
|
||||
`!shared-bindings` and a growing list of drivers that work with it. Currently
|
||||
only the Atmel SAMD21 port is supported but ESP8266 support will be added in the
|
||||
near future.
|
||||
|
||||
@ -23,6 +23,7 @@ docs are low-level API docs and may link out to separate getting started guides.
|
||||
:maxdepth: 2
|
||||
|
||||
shared-bindings/index.rst
|
||||
docs/common_hal
|
||||
docs/drivers.rst
|
||||
docs/supported_ports.rst
|
||||
docs/unsupported_ports.rst
|
||||
|
@ -29,6 +29,8 @@
|
||||
|
||||
#define likely(x) __builtin_expect((x), 1)
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
void *memcpy(void *dst, const void *src, size_t n) {
|
||||
if (likely(!(((uintptr_t)dst) & 3) && !(((uintptr_t)src) & 3))) {
|
||||
// pointers aligned
|
||||
@ -102,6 +104,8 @@ void *memset(void *s, int c, size_t n) {
|
||||
return s;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||
const uint8_t *s1_8 = s1;
|
||||
const uint8_t *s2_8 = s2;
|
||||
|
@ -134,7 +134,7 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args,
|
||||
mp_arg_parse_all(n_pos, args, &kw_args, n_allowed, allowed, out_vals);
|
||||
}
|
||||
|
||||
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || _MSC_VER
|
||||
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || defined(_MSC_VER)
|
||||
NORETURN void mp_arg_error_terse_mismatch(void) {
|
||||
mp_raise_msg(&mp_type_TypeError, "argument num/types mismatch");
|
||||
}
|
||||
|
13
py/gc.c
13
py/gc.c
@ -392,6 +392,16 @@ void gc_info(gc_info_t *info) {
|
||||
GC_EXIT();
|
||||
}
|
||||
|
||||
void gc_mark_block(void * ptr) {
|
||||
if (VERIFY_PTR(ptr)) {
|
||||
size_t _block = BLOCK_FROM_PTR(ptr);
|
||||
if (ATB_GET_KIND(_block) == AT_HEAD) {
|
||||
/* an unmarked head, mark it, and push it on gc stack */
|
||||
ATB_HEAD_TO_MARK(_block);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void *gc_alloc(size_t n_bytes, bool has_finaliser) {
|
||||
size_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1) & (~(BYTES_PER_BLOCK - 1))) / BYTES_PER_BLOCK;
|
||||
DEBUG_printf("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n", n_bytes, n_blocks);
|
||||
@ -833,7 +843,10 @@ void gc_dump_alloc_table(void) {
|
||||
*/
|
||||
/* this prints the uPy object type of the head block */
|
||||
case AT_HEAD: {
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
void **ptr = (void**)(MP_STATE_MEM(gc_pool_start) + bl * BYTES_PER_BLOCK);
|
||||
#pragma GCC diagnostic pop
|
||||
if (*ptr == &mp_type_tuple) { c = 'T'; }
|
||||
else if (*ptr == &mp_type_list) { c = 'L'; }
|
||||
else if (*ptr == &mp_type_dict) { c = 'D'; }
|
||||
|
3
py/gc.h
3
py/gc.h
@ -45,6 +45,9 @@ void gc_collect_start(void);
|
||||
void gc_collect_root(void **ptrs, size_t len);
|
||||
void gc_collect_end(void);
|
||||
|
||||
// During a collect, use this to mark blocks used in C but allocated using gc_alloc.
|
||||
void gc_mark_block(void * ptr);
|
||||
|
||||
void *gc_alloc(size_t n_bytes, bool has_finaliser);
|
||||
void gc_free(void *ptr); // does not call finaliser
|
||||
size_t gc_nbytes(const void *ptr);
|
||||
|
@ -470,9 +470,9 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) {
|
||||
mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val);
|
||||
mp_int_t r = rounded;
|
||||
// make rounded value even if it was halfway between ints
|
||||
if (val - rounded == 0.5) {
|
||||
if (val - rounded >= 0.5) {
|
||||
r = (r + 1) & (~1);
|
||||
} else if (val - rounded == -0.5) {
|
||||
} else if (val - rounded <= -0.5) {
|
||||
r &= ~1;
|
||||
}
|
||||
if (n_args > 1) {
|
||||
|
@ -70,7 +70,7 @@ STATIC NORETURN void math_error(void) {
|
||||
} \
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
#if MP_NEED_LOG2
|
||||
#ifdef MP_NEED_LOG2
|
||||
// 1.442695040888963407354163704 is 1/_M_LN2
|
||||
#define log2(x) (log(x) * 1.442695040888963407354163704)
|
||||
#endif
|
||||
|
@ -146,12 +146,12 @@ typedef struct _mp_state_vm_t {
|
||||
|
||||
// root pointers for extmod
|
||||
|
||||
#if MICROPY_PY_OS_DUPTERM
|
||||
#ifdef MICROPY_PY_OS_DUPTERM
|
||||
mp_obj_t term_obj;
|
||||
mp_obj_t dupterm_arr_obj;
|
||||
#endif
|
||||
|
||||
#if MICROPY_PY_LWIP_SLIP
|
||||
#ifdef MICROPY_PY_LWIP_SLIP
|
||||
mp_obj_t lwip_slip_stream;
|
||||
#endif
|
||||
|
||||
|
1
py/nlr.h
1
py/nlr.h
@ -41,6 +41,7 @@ struct _nlr_buf_t {
|
||||
nlr_buf_t *prev;
|
||||
void *ret_val; // always a concrete object (an exception instance)
|
||||
#if !defined(MICROPY_NLR_SETJMP) || !MICROPY_NLR_SETJMP
|
||||
#define MICROPY_NLR_SETJMP (0)
|
||||
#if defined(__i386__)
|
||||
void *regs[6];
|
||||
#elif defined(__x86_64__)
|
||||
|
2
py/obj.h
2
py/obj.h
@ -513,8 +513,6 @@ struct _mp_obj_type_t {
|
||||
extern const mp_obj_type_t mp_type_type;
|
||||
extern const mp_obj_type_t mp_type_object;
|
||||
extern const mp_obj_type_t mp_type_NoneType;
|
||||
extern const mp_obj_type_t mp_type_bool;
|
||||
extern const mp_obj_type_t mp_type_int;
|
||||
extern const mp_obj_type_t mp_type_str;
|
||||
extern const mp_obj_type_t mp_type_bytes;
|
||||
extern const mp_obj_type_t mp_type_bytearray;
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include <math.h>
|
||||
#include "py/formatfloat.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
|
||||
typedef struct _mp_obj_complex_t {
|
||||
mp_obj_base_t base;
|
||||
mp_float_t real;
|
||||
@ -248,4 +251,6 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t
|
||||
return mp_obj_new_complex(lhs_real, lhs_imag);
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include <math.h>
|
||||
#include "py/formatfloat.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||
|
||||
#if MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_C && MICROPY_OBJ_REPR != MICROPY_OBJ_REPR_D
|
||||
|
||||
// M_E and M_PI are not part of the math.h standard and may not be defined
|
||||
@ -252,4 +255,6 @@ mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_i
|
||||
return mp_obj_new_float(lhs_val);
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#endif // MICROPY_PY_BUILTINS_FLOAT
|
||||
|
@ -201,13 +201,13 @@ STATIC const mp_rom_map_elem_t mp_builtin_module_table[] = {
|
||||
#if MICROPY_PY_USSL
|
||||
{ MP_ROM_QSTR(MP_QSTR_ussl), MP_ROM_PTR(&mp_module_ussl) },
|
||||
#endif
|
||||
#if MICROPY_PY_LWIP
|
||||
#ifdef MICROPY_PY_LWIP
|
||||
{ MP_ROM_QSTR(MP_QSTR_lwip), MP_ROM_PTR(&mp_module_lwip) },
|
||||
#endif
|
||||
#if MICROPY_PY_WEBSOCKET
|
||||
{ MP_ROM_QSTR(MP_QSTR_websocket), MP_ROM_PTR(&mp_module_websocket) },
|
||||
#endif
|
||||
#if MICROPY_PY_WEBREPL
|
||||
#ifdef MICROPY_PY_WEBREPL
|
||||
{ MP_ROM_QSTR(MP_QSTR__webrepl), MP_ROM_PTR(&mp_module_webrepl) },
|
||||
#endif
|
||||
#if MICROPY_PY_FRAMEBUF
|
||||
|
@ -28,15 +28,11 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/objproperty.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if MICROPY_PY_BUILTINS_PROPERTY
|
||||
|
||||
typedef struct _mp_obj_property_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t proxy[3]; // getter, setter, deleter
|
||||
} mp_obj_property_t;
|
||||
|
||||
STATIC mp_obj_t property_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
enum { ARG_fget, ARG_fset, ARG_fdel, ARG_doc };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
|
40
py/objproperty.h
Normal file
40
py/objproperty.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of the Micro Python project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2013, 2014 Damien P. George
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef __MICROPY_INCLUDED_PY_OBJPROPERTY_H__
|
||||
#define __MICROPY_INCLUDED_PY_OBJPROPERTY_H__
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
#if MICROPY_PY_BUILTINS_PROPERTY
|
||||
|
||||
typedef struct _mp_obj_property_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t proxy[3]; // getter, setter, deleter
|
||||
} mp_obj_property_t;
|
||||
|
||||
#endif // MICROPY_PY_BUILTINS_PROPERTY
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_OBJPROPERTY_H__
|
@ -110,7 +110,10 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
|
||||
// this should not be applied to class types, as will result in extra
|
||||
// lookup either.
|
||||
if (lookup->meth_offset != 0 && mp_obj_is_native_type(type)) {
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
if (*(void**)((char*)type + lookup->meth_offset) != NULL) {
|
||||
#pragma GCC diagnostic pop
|
||||
DEBUG_printf("mp_obj_class_lookup: matched special meth slot for %s\n", qstr_str(lookup->attr));
|
||||
lookup->dest[0] = MP_OBJ_SENTINEL;
|
||||
return;
|
||||
@ -368,7 +371,7 @@ STATIC mp_obj_t instance_unary_op(mp_uint_t op, mp_obj_t self_in) {
|
||||
if (member[0] == MP_OBJ_NULL) {
|
||||
// https://docs.python.org/3/reference/datamodel.html#object.__hash__
|
||||
// "User-defined classes have __eq__() and __hash__() methods by default;
|
||||
// with them, all objects compare unequal (except with themselves) and
|
||||
// with them, all objects compare unequal (except with themselves) and
|
||||
// x.__hash__() returns an appropriate value such that x == y implies
|
||||
// both that x is y and hash(x) == hash(y)."
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_uint_t)self_in);
|
||||
|
@ -152,6 +152,8 @@ typedef struct _parser_t {
|
||||
#endif
|
||||
} parser_t;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-align"
|
||||
STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
|
||||
// use a custom memory allocator to store parse nodes sequentially in large chunks
|
||||
|
||||
@ -192,6 +194,7 @@ STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
|
||||
chunk->union_.used += num_bytes;
|
||||
return ret;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) {
|
||||
if (parser->parse_error) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user