diff options
| author | Scott Shawcroft <scott@chickadee.tech> | 2016-09-13 11:46:22 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott@chickadee.tech> | 2016-09-13 11:46:22 -0700 |
| commit | 7d8929c470f7c7215d93cbe90d713e7b60d93dd6 (patch) | |
| tree | a6318806cc968b271c70b20d93e0a3faafa9c5be | |
| parent | 05368d2c581b730911610425d87ccf2b5fda82a5 (diff) | |
atmel-samd: Add I2C support.
This commit also introduces a new shared-bindings directory which is used to store the common Python -> C binding code. By having a shared directory we can ensure that the Python API across ports is the same. Each port will have a corresponding common-hal directory which provides definitions for the C api used in the shared-bindings code. That way the compiler can enforce the C api.
To migrate to this new shared API create a common-hal directory within your port and change the Makefile to compile both the shared-bindings and common-hal files. See atmel-samd/Makefile SRC_BINDINGS for an example.
| -rw-r--r-- | atmel-samd/Makefile | 45 | ||||
| -rw-r--r-- | atmel-samd/boards/arduino_zero/pins.c | 159 | ||||
| -rw-r--r-- | atmel-samd/boards/feather_m0_bluefruit_le/pins.c | 150 | ||||
| -rw-r--r-- | atmel-samd/common-hal/modules/machine.c | 200 | ||||
| -rw-r--r-- | atmel-samd/common-hal/modules/machine_types.h | 80 | ||||
| -rw-r--r-- | atmel-samd/modmachine.c | 6 | ||||
| -rw-r--r-- | atmel-samd/modmachine_pin.h | 79 | ||||
| -rw-r--r-- | atmel-samd/mpconfigport.h | 22 | ||||
| -rw-r--r-- | shared-bindings/modules/machine.c | 285 | ||||
| -rw-r--r-- | shared-bindings/modules/machine.h | 77 |
10 files changed, 917 insertions, 186 deletions
diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index a4b08a59d..bd5bd1e1d 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -18,24 +18,20 @@ include boards/$(BOARD)/mpconfigboard.mk # Add $(BUILD)/pins_qstr.h $(BUILD)/modstm_qstr.h QSTR_DEFS = qstrdefsport.h -CROSS = 0 - # include py core make definitions include ../py/py.mk -ifeq ($(CROSS), 1) CROSS_COMPILE = arm-none-eabi- -endif BOSSAC := /Users/tannewt/ArduinoCore-samd/tools/bossac_osx - HAL_DIR=hal/$(MCU_SERIES) INC += -I. INC += -I.. INC += -I../lib/mp-readline INC += -I../lib/timeutils +INC += -Icommon-hal/modules/ INC += -Iasf/common/boards/ INC += -Iasf/common/services/sleepmgr/ INC += -Iasf/common/services/usb/ @@ -51,6 +47,8 @@ INC += $(addprefix -Iasf/sam0/,\ drivers/adc/adc_sam_d_r \ drivers/dac \ drivers/dac/dac_sam_d_c \ + drivers/sercom \ + drivers/sercom/i2c \ drivers/system/clock \ drivers/system/clock/clock_samd21_r21_da \ drivers/system/interrupt \ @@ -58,9 +56,8 @@ INC += $(addprefix -Iasf/sam0/,\ drivers/system/pinmux \ drivers/system/power/power_sam_d_r \ drivers/system/reset/reset_sam_d_r \ - drivers/sercom/ \ - drivers/tc/ \ - drivers/usb/ \ + drivers/tc \ + drivers/usb \ utils \ utils/cmsis/samd21/include \ utils/cmsis/samd21/source \ @@ -71,7 +68,6 @@ INC += -Iasf/thirdparty/CMSIS/Include INC += -Iboards/$(BOARD)/ INC += -I$(BUILD) -ifeq ($(CROSS), 1) CFLAGS_CORTEX_M0 = \ -mthumb \ -mabi=aapcs-linux \ @@ -94,9 +90,6 @@ CFLAGS_CORTEX_M0 = \ -DUSART_CALLBACK_MODE=true \ -DUSB_DEVICE_LPM_SUPPORT CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M0) $(COPT) -else -CFLAGS = -m32 $(INC) -Wall -Werror -ansi -std=gnu99 $(COPT) -endif #Debugging/Optimization ifeq ($(DEBUG), 1) @@ -105,16 +98,10 @@ else CFLAGS += -Os -DNDEBUG endif -LIBS = -ifeq ($(CROSS), 1) LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) LIBM_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-file-name=libm.a) LDFLAGS = -Lasf/thirdparty/CMSIS/Lib/GCC/ -L $(dir $(LIBGCC_FILE_NAME)) -L $(dir $(LIBM_FILE_NAME)) -nostdlib -T $(LD_FILE) -Map=$@.map --cref --gc-sections -LIBS += -larm_cortexM0l_math -lm -lgcc -lc -else -LD = gcc -LDFLAGS = -m32 -Wl,-Map=$@.map,--cref -endif +LIBS = -larm_cortexM0l_math -lm -lgcc -lc SRC_ASF = $(addprefix asf/sam0/,\ @@ -122,6 +109,7 @@ SRC_ASF = $(addprefix asf/sam0/,\ drivers/dac/dac_sam_d_c/dac.c \ drivers/nvm/nvm.c \ drivers/port/port.c \ + drivers/sercom/i2c/i2c_sam0/i2c_master.c \ drivers/sercom/sercom.c \ drivers/sercom/sercom_interrupt.c \ drivers/sercom/usart/usart.c \ @@ -160,7 +148,7 @@ SRC_C = \ asf/common/utils/interrupt/interrupt_sam_nvic.c \ asf/common2/services/delay/sam0/systick_counter.c \ asf/sam0/utils/cmsis/samd21/source/gcc/startup_samd21.c \ - asf/sam0/utils/cmsis/samd21/source/system_samd21.c \ + asf/sam0/utils/cmsis/samd21/source/system_samd21.c \ asf/sam0/utils/syscalls/gcc/syscalls.c \ boards/$(BOARD)/pins.c \ lib/fatfs/ff.c \ @@ -172,20 +160,27 @@ SRC_C = \ lib/libc/string0.c \ lib/mp-readline/readline.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 + +SRC_BINDINGS_EXPANDED = $(addprefix shared-bindings/, $(SRC_BINDINGS)) \ + $(addprefix common-hal/, $(SRC_BINDINGS)) + SRC_AUTOGEN = \ $(BUILD)/_frozen_mpy.c \ OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_ASF:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_AUTOGEN:.c=.o)) +OBJ += $(addprefix $(BUILD)/, $(SRC_BINDINGS_EXPANDED:.c=.o)) -SRC_QSTR += $(SRC_C) +SRC_QSTR += $(SRC_C) $(SRC_BINDINGS_EXPANDED) -ifeq ($(CROSS), 1) all: $(BUILD)/firmware.bin -else -all: $(BUILD)/firmware.elf -endif $(BUILD)/_frozen_mpy.c: frozentest.mpy $(BUILD)/genhdr/qstrdefs.generated.h $(ECHO) "MISC freezing bytecode" diff --git a/atmel-samd/boards/arduino_zero/pins.c b/atmel-samd/boards/arduino_zero/pins.c index 8f866a232..df51aadc0 100644 --- a/atmel-samd/boards/arduino_zero/pins.c +++ b/atmel-samd/boards/arduino_zero/pins.c @@ -1,54 +1,113 @@ #include "pins.h" #include "asf/sam0/drivers/system/system.h" -PIN_NO_TIMERS_(PA02, true, ADC_POSITIVE_INPUT_PIN0); -PIN_ONE_TIMER_(PB08, true, ADC_POSITIVE_INPUT_PIN8, - TC4, 0, 0, 0, PIN_PB08E_TC4_WO0, MUX_PB08E_TC4_WO0); -PIN_ONE_TIMER_(PB09, true, ADC_POSITIVE_INPUT_PIN9, - TC4, 0, 1, 1, PIN_PB09E_TC4_WO1, MUX_PB09E_TC4_WO1); -PIN_ONE_TIMER_(PA04, true, ADC_POSITIVE_INPUT_PIN4, - 0, TCC0, 0, 0, PIN_PA04E_TCC0_WO0, MUX_PA04E_TCC0_WO0); -PIN_ONE_TIMER_(PA05, true, ADC_POSITIVE_INPUT_PIN5, - 0, TCC0, 1, 1, PIN_PA05E_TCC0_WO1, MUX_PA05E_TCC0_WO1); -PIN_NO_TIMERS_(PB02, true, ADC_POSITIVE_INPUT_PIN10); -PIN_TWO_TIMERS(PA11, true, ADC_POSITIVE_INPUT_PIN19, - 0, TCC1, 1, 1, PIN_PA11E_TCC1_WO1, MUX_PA11E_TCC1_WO1, - 0, TCC0, 3, 3, PIN_PA11F_TCC0_WO3, MUX_PA11F_TCC0_WO3); -PIN_TWO_TIMERS(PA10, true, ADC_POSITIVE_INPUT_PIN18, - 0, TCC1, 0, 0, PIN_PA10E_TCC1_WO0, MUX_PA10E_TCC1_WO0, - 0, TCC0, 2, 2, PIN_PA10F_TCC0_WO2, MUX_PA10F_TCC0_WO2); -PIN_TWO_TIMERS(PA14, false, NO_ADC_INPUT, - TC3, 0, 0, 0, PIN_PA14E_TC3_WO0, MUX_PA14E_TC3_WO0, - 0, TCC0, 0, 4, PIN_PA14F_TCC0_WO4, MUX_PA14F_TCC0_WO4); -PIN_TWO_TIMERS(PA09, true, ADC_POSITIVE_INPUT_PIN17, - 0, TCC0, 1, 1, PIN_PA09E_TCC0_WO1, MUX_PA09E_TCC0_WO1, - 0, TCC1, 3, 3, PIN_PA09F_TCC1_WO3, MUX_PA09F_TCC1_WO3); -PIN_TWO_TIMERS(PA08, true, ADC_POSITIVE_INPUT_PIN16, - 0, TCC0, 0, 0, PIN_PA08E_TCC0_WO0, MUX_PA08E_TCC0_WO0, - 0, TCC1, 2, 2, PIN_PA08F_TCC1_WO2, MUX_PA08F_TCC1_WO2); -PIN_TWO_TIMERS(PA15, false, NO_ADC_INPUT, - TC3, 0, 1, 1, PIN_PA15E_TC3_WO1, MUX_PA15E_TC3_WO1, - 0, TCC0, 1, 5, PIN_PA15F_TCC0_WO5, MUX_PA15F_TCC0_WO5); -PIN_ONE_TIMER_(PA20, false, NO_ADC_INPUT, - 0, TCC0, 2, 6, PIN_PA20F_TCC0_WO6, MUX_PA20F_TCC0_WO6); -PIN_ONE_TIMER_(PA21, false, NO_ADC_INPUT, - 0, TCC0, 3, 7, PIN_PA21F_TCC0_WO7, MUX_PA21F_TCC0_WO7); -PIN_ONE_TIMER_(PA06, true, ADC_POSITIVE_INPUT_PIN6, - 0, TCC1, 0, 0, PIN_PA06E_TCC1_WO0, MUX_PA06E_TCC1_WO0); -PIN_ONE_TIMER_(PA07, true, ADC_POSITIVE_INPUT_PIN7, - 0, TCC1, 1, 1, PIN_PA07E_TCC1_WO1, MUX_PA07E_TCC1_WO1); -PIN_TWO_TIMERS(PA18, false, NO_ADC_INPUT, - TC3, 0, 0, 0, PIN_PA18E_TC3_WO0, MUX_PA18E_TC3_WO0, - 0, TCC0, 2, 2, PIN_PA18F_TCC0_WO2, MUX_PA18F_TCC0_WO2); -PIN_TWO_TIMERS(PA16, false, NO_ADC_INPUT, - 0, TCC2, 0, 0, PIN_PA16E_TCC2_WO0, MUX_PA16E_TCC2_WO0, - 0, TCC0, 2, 6, PIN_PA16F_TCC0_WO6, MUX_PA16F_TCC0_WO6); -PIN_TWO_TIMERS(PA19, false, NO_ADC_INPUT, - TC3, 0, 1, 1, PIN_PA19E_TC3_WO1, MUX_PA19E_TC3_WO1, - 0, TCC0, 3, 3, PIN_PA19F_TCC0_WO3, MUX_PA19F_TCC0_WO3); -PIN_TWO_TIMERS(PA17, false, NO_ADC_INPUT, - 0, TCC2, 1, 1, PIN_PA17E_TCC2_WO1, MUX_PA17E_TCC2_WO1, - 0, TCC0, 3, 7, PIN_PA17F_TCC0_WO7, MUX_PA17F_TCC0_WO7); +PIN(PA02, true, ADC_POSITIVE_INPUT_PIN0, NO_TIMER, NO_TIMER, NO_SERCOM, + NO_SERCOM); +PIN(PB08, true, ADC_POSITIVE_INPUT_PIN8, + TIMER(TC4, 0, 0, 0, PIN_PB08E_TC4_WO0, MUX_PB08E_TC4_WO0), + NO_TIMER, + SERCOM(SERCOM4, 0, PINMUX_PB08D_SERCOM4_PAD0), + NO_SERCOM); +PIN(PB09, true, ADC_POSITIVE_INPUT_PIN9, + TIMER(TC4, 0, 1, 1, PIN_PB09E_TC4_WO1, MUX_PB09E_TC4_WO1), + NO_TIMER, + SERCOM(SERCOM4, 1, PINMUX_PB09D_SERCOM4_PAD1), + NO_SERCOM); +PIN(PA04, true, ADC_POSITIVE_INPUT_PIN4, + TIMER(0, TCC0, 0, 0, PIN_PA04E_TCC0_WO0, MUX_PA04E_TCC0_WO0), + NO_TIMER, + SERCOM(SERCOM0, 0, PINMUX_PA04D_SERCOM0_PAD0), + NO_SERCOM); +PIN(PA05, true, ADC_POSITIVE_INPUT_PIN5, + TIMER(0, TCC0, 1, 1, PIN_PA05E_TCC0_WO1, MUX_PA05E_TCC0_WO1), + NO_TIMER, + SERCOM(SERCOM0, 1, PINMUX_PA05D_SERCOM0_PAD1), + NO_SERCOM); +PIN(PB02, true, ADC_POSITIVE_INPUT_PIN10, + NO_TIMER, + NO_TIMER, + SERCOM(SERCOM5, 0, PINMUX_PB02D_SERCOM5_PAD0), + NO_SERCOM); +PIN(PA11, true, ADC_POSITIVE_INPUT_PIN19, + TIMER(0, TCC1, 1, 1, PIN_PA11E_TCC1_WO1, MUX_PA11E_TCC1_WO1), + TIMER(0, TCC0, 3, 3, PIN_PA11F_TCC0_WO3, MUX_PA11F_TCC0_WO3), + SERCOM(SERCOM0, 3, PINMUX_PA11C_SERCOM0_PAD3), + SERCOM(SERCOM2, 3, PINMUX_PA11D_SERCOM2_PAD3)); +PIN(PA10, true, ADC_POSITIVE_INPUT_PIN18, + TIMER(0, TCC1, 0, 0, PIN_PA10E_TCC1_WO0, MUX_PA10E_TCC1_WO0), + TIMER(0, TCC0, 2, 2, PIN_PA10F_TCC0_WO2, MUX_PA10F_TCC0_WO2), + SERCOM(SERCOM0, 2, PINMUX_PA10C_SERCOM0_PAD2), + SERCOM(SERCOM2, 2, PINMUX_PA10D_SERCOM2_PAD2)); +PIN(PA14, false, NO_ADC_INPUT, + TIMER(TC3, 0, 0, 0, PIN_PA14E_TC3_WO0, MUX_PA14E_TC3_WO0), + TIMER(0, TCC0, 0, 4, PIN_PA14F_TCC0_WO4, MUX_PA14F_TCC0_WO4), + SERCOM(SERCOM2, 2, PINMUX_PA14C_SERCOM2_PAD2), + SERCOM(SERCOM4, 2, PINMUX_PA14D_SERCOM4_PAD2)); +PIN(PA09, true, ADC_POSITIVE_INPUT_PIN17, + TIMER(0, TCC0, 1, 1, PIN_PA09E_TCC0_WO1, MUX_PA09E_TCC0_WO1), + TIMER(0, TCC1, 3, 3, PIN_PA09F_TCC1_WO3, MUX_PA09F_TCC1_WO3), + SERCOM(SERCOM0, 1, PINMUX_PA09C_SERCOM0_PAD1), + SERCOM(SERCOM2, 1, PINMUX_PA09D_SERCOM2_PAD1)); +PIN(PA08, true, ADC_POSITIVE_INPUT_PIN16, + TIMER(0, TCC0, 0, 0, PIN_PA08E_TCC0_WO0, MUX_PA08E_TCC0_WO0), + TIMER(0, TCC1, 2, 2, PIN_PA08F_TCC1_WO2, MUX_PA08F_TCC1_WO2), + SERCOM(SERCOM0, 0, PINMUX_PA08C_SERCOM0_PAD0), + SERCOM(SERCOM2, 0, PINMUX_PA08D_SERCOM2_PAD0)); +PIN(PA15, false, NO_ADC_INPUT, + TIMER(TC3, 0, 1, 1, PIN_PA15E_TC3_WO1, MUX_PA15E_TC3_WO1), + TIMER(0, TCC0, 1, 5, PIN_PA15F_TCC0_WO5, MUX_PA15F_TCC0_WO5), + SERCOM(SERCOM2, 3, PINMUX_PA15C_SERCOM2_PAD3), + SERCOM(SERCOM4, 3, PINMUX_PA15D_SERCOM4_PAD3)); +PIN(PA20, false, NO_ADC_INPUT, + TIMER(0, TCC0, 2, 6, PIN_PA20F_TCC0_WO6, MUX_PA20F_TCC0_WO6), + NO_TIMER, + SERCOM(SERCOM5, 2, PINMUX_PA20C_SERCOM5_PAD2), + SERCOM(SERCOM3, 2, PINMUX_PA20D_SERCOM3_PAD2)); +PIN(PA21, false, NO_ADC_INPUT, + TIMER(0, TCC0, 3, 7, PIN_PA21F_TCC0_WO7, MUX_PA21F_TCC0_WO7), + NO_TIMER, + SERCOM(SERCOM5, 3, PINMUX_PA21C_SERCOM5_PAD3), + SERCOM(SERCOM3, 3, PINMUX_PA21D_SERCOM3_PAD3)); +PIN(PA06, true, ADC_POSITIVE_INPUT_PIN6, + TIMER(0, TCC1, 0, 0, PIN_PA06E_TCC1_WO0, MUX_PA06E_TCC1_WO0), + NO_TIMER, + SERCOM(SERCOM0, 2, PINMUX_PA06D_SERCOM0_PAD2), + NO_SERCOM); +PIN(PA07, true, ADC_POSITIVE_INPUT_PIN7, + TIMER(0, TCC1, 1, 1, PIN_PA07E_TCC1_WO1, MUX_PA07E_TCC1_WO1), + NO_TIMER, + SERCOM(SERCOM0, 3, PINMUX_PA07D_SERCOM0_PAD3), + NO_SERCOM); +PIN(PA18, false, NO_ADC_INPUT, + TIMER(TC3, 0, 0, 0, PIN_PA18E_TC3_WO0, MUX_PA18E_TC3_WO0), + TIMER(0, TCC0, 2, 2, PIN_PA18F_TCC0_WO2, MUX_PA18F_TCC0_WO2), + SERCOM(SERCOM1, 2, PINMUX_PA18C_SERCOM1_PAD2), + SERCOM(SERCOM3, 2, PINMUX_PA18D_SERCOM3_PAD2)); +PIN(PA16, false, NO_ADC_INPUT, + TIMER(0, TCC2, 0, 0, PIN_PA16E_TCC2_WO0, MUX_PA16E_TCC2_WO0), + TIMER(0, TCC0, 2, 6, PIN_PA16F_TCC0_WO6, MUX_PA16F_TCC0_WO6), + SERCOM(SERCOM1, 0, PINMUX_PA16C_SERCOM1_PAD0), + SERCOM(SERCOM3, 0, PINMUX_PA16D_SERCOM3_PAD0)); +PIN(PA19, false, NO_ADC_INPUT, + TIMER(TC3, 0, 1, 1, PIN_PA19E_TC3_WO1, MUX_PA19E_TC3_WO1), + TIMER(0, TCC0, 3, 3, PIN_PA19F_TCC0_WO3, MUX_PA19F_TCC0_WO3), + SERCOM(SERCOM1, 3, PINMUX_PA19C_SERCOM1_PAD3), + SERCOM(SERCOM3, 3, PINMUX_PA19C_SERCOM1_PAD3)); +PIN(PA17, false, NO_ADC_INPUT, + TIMER(0, TCC2, 1, 1, PIN_PA17E_TCC2_WO1, MUX_PA17E_TCC2_WO1), + TIMER(0, TCC0, 3, 7, PIN_PA17F_TCC0_WO7, MUX_PA17F_TCC0_WO7), + SERCOM(SERCOM1, 1, PINMUX_PA17C_SERCOM1_PAD1), + SERCOM(SERCOM3, 1, PINMUX_PA17D_SERCOM3_PAD1)); +PIN(PA22, false, NO_ADC_INPUT, + TIMER(TC4, 0, 0, 0, PIN_PA22E_TC4_WO0, MUX_PA22E_TC4_WO0), + TIMER(0, TCC0, 0, 4, PIN_PA22F_TCC0_WO4, MUX_PA22F_TCC0_WO4), + SERCOM(SERCOM3, 0, PINMUX_PA22C_SERCOM3_PAD0), + SERCOM(SERCOM5, 0, PINMUX_PA22D_SERCOM5_PAD0)); +PIN(PA23, false, NO_ADC_INPUT, + TIMER(TC4, 0, 1, 1, PIN_PA23E_TC4_WO1, MUX_PA23E_TC4_WO1), + TIMER(0, TCC0, 1, 5, PIN_PA23F_TCC0_WO5, MUX_PA23F_TCC0_WO5), + SERCOM(SERCOM3, 1, PINMUX_PA23C_SERCOM3_PAD1), + SERCOM(SERCOM5, 1, PINMUX_PA23C_SERCOM3_PAD1)); STATIC const mp_map_elem_t pin_cpu_pins_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_PA02), (mp_obj_t)&pin_PA02 }, @@ -71,6 +130,8 @@ STATIC const mp_map_elem_t pin_cpu_pins_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_PA16), (mp_obj_t)&pin_PA16 }, { MP_OBJ_NEW_QSTR(MP_QSTR_PA19), (mp_obj_t)&pin_PA19 }, { MP_OBJ_NEW_QSTR(MP_QSTR_PA17), (mp_obj_t)&pin_PA17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA22), (mp_obj_t)&pin_PA22 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_PA23), (mp_obj_t)&pin_PA23 }, }; MP_DEFINE_CONST_DICT(pin_cpu_pins_locals_dict, pin_cpu_pins_locals_dict_table); @@ -95,5 +156,7 @@ STATIC const mp_map_elem_t pin_board_pins_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_D11), (mp_obj_t)&pin_PA16 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D12), (mp_obj_t)&pin_PA19 }, { MP_OBJ_NEW_QSTR(MP_QSTR_D13), (mp_obj_t)&pin_PA17 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SDA), (mp_obj_t)&pin_PA22 }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SCL), (mp_obj_t)&pin_PA23 }, }; MP_DEFINE_CONST_DICT(pin_board_pins_locals_dict, pin_board_pins_locals_dict_table); diff --git a/atmel-samd/boards/feather_m0_bluefruit_le/pins.c b/atmel-samd/boards/feather_m0_bluefruit_le/pins.c index b60d7562f..5ffa433d0 100644 --- a/atmel-samd/boards/feather_m0_bluefruit_le/pins.c +++ b/atmel-samd/boards/feather_m0_bluefruit_le/pins.c @@ -1,56 +1,104 @@ #include "pins.h" #include "asf/sam0/drivers/system/system.h" - -PIN_NO_TIMERS_(PA02, true, ADC_POSITIVE_INPUT_PIN0); -PIN_ONE_TIMER_(PB08, true, ADC_POSITIVE_INPUT_PIN8, - TC4, 0, 0, 0, PIN_PB08E_TC4_WO0, MUX_PB08E_TC4_WO0); -PIN_ONE_TIMER_(PB09, true, ADC_POSITIVE_INPUT_PIN9, - TC4, 0, 1, 1, PIN_PB09E_TC4_WO1, MUX_PB09E_TC4_WO1); -PIN_ONE_TIMER_(PA04, true, ADC_POSITIVE_INPUT_PIN4, - 0, TCC0, 0, 0, PIN_PA04E_TCC0_WO0, MUX_PA04E_TCC0_WO0); -PIN_ONE_TIMER_(PA05, true, ADC_POSITIVE_INPUT_PIN5, - 0, TCC0, 1, 1, PIN_PA05E_TCC0_WO1, MUX_PA05E_TCC0_WO1); -PIN_NO_TIMERS_(PB02, true, ADC_POSITIVE_INPUT_PIN10); -PIN_TWO_TIMERS(PB11, false, NO_ADC_INPUT, - TC5, 0, 1, 1, PIN_PB11E_TC5_WO1, MUX_PB11E_TC5_WO1, - 0, TCC0, 1, 5, PIN_PB11F_TCC0_WO5, MUX_PB11F_TCC0_WO5); -PIN_TWO_TIMERS(PB10, false, NO_ADC_INPUT, - TC5, 0, 0, 0, PIN_PB10E_TC5_WO0, MUX_PB10E_TC5_WO0, - 0, TCC0, 0, 4, PIN_PB10F_TCC0_WO4, MUX_PB10F_TCC0_WO4); -PIN_TWO_TIMERS(PA12, false, NO_ADC_INPUT, - 0, TCC2, 0, 0, PIN_PA12E_TCC2_WO0, MUX_PA12E_TCC2_WO0, - 0, TCC0, 2, 6, PIN_PA12F_TCC0_WO6, MUX_PA12F_TCC0_WO6); -PIN_TWO_TIMERS(PA11, true, ADC_POSITIVE_INPUT_PIN19, - 0, TCC1, 1, 1, PIN_PA11E_TCC1_WO1, MUX_PA11E_TCC1_WO1, - 0, TCC0, 3, 3, PIN_PA11F_TCC0_WO3, MUX_PA11F_TCC0_WO3); -PIN_TWO_TIMERS(PA10, true, ADC_POSITIVE_INPUT_PIN18, - 0, TCC1, 0, 0, PIN_PA10E_TCC1_WO0, MUX_PA10E_TCC1_WO0, - 0, TCC0, 2, 2, PIN_PA10F_TCC0_WO2, MUX_PA10F_TCC0_WO2); -PIN_TWO_TIMERS(PA22, false, NO_ADC_INPUT, - TC4, 0, 0, 0, PIN_PA22E_TC4_WO0, MUX_PA22E_TC4_WO0, - 0, TCC0, 0, 4, PIN_PA22F_TCC0_WO4, MUX_PA22F_TCC0_WO4); -PIN_TWO_TIMERS(PA23, false, NO_ADC_INPUT, - TC4, 0, 1, 1, PIN_PA23E_TC4_WO1, MUX_PA23E_TC4_WO1, - 0, TCC0, 1, 5, PIN_PA23F_TCC0_WO5, MUX_PA23F_TCC0_WO5); -PIN_TWO_TIMERS(PA15, false, NO_ADC_INPUT, - TC3, 0, 1, 1, PIN_PA15E_TC3_WO1, MUX_PA15E_TC3_WO1, - 0, TCC0, 1, 5, PIN_PA15F_TCC0_WO5, MUX_PA15F_TCC0_WO5); -PIN_ONE_TIMER_(PA20, false, NO_ADC_INPUT, - 0, TCC0, 2, 6, PIN_PA20F_TCC0_WO6, MUX_PA20F_TCC0_WO6); -PIN_ONE_TIMER_(PA07, true, ADC_POSITIVE_INPUT_PIN7, - 0, TCC1, 1, 1, PIN_PA07E_TCC1_WO1, MUX_PA07E_TCC1_WO1); -PIN_TWO_TIMERS(PA18, false, NO_ADC_INPUT, - TC3, 0, 0, 0, PIN_PA18E_TC3_WO0, MUX_PA18E_TC3_WO0, - 0, TCC0, 2, 2, PIN_PA18F_TCC0_WO2, MUX_PA18F_TCC0_WO2); -PIN_TWO_TIMERS(PA16, false, NO_ADC_INPUT, - 0, TCC2, 0, 0, PIN_PA16E_TCC2_WO0, MUX_PA16E_TCC2_WO0, - 0, TCC0, 2, 6, PIN_PA16F_TCC0_WO6, MUX_PA16F_TCC0_WO6); -PIN_TWO_TIMERS(PA19, false, NO_ADC_INPUT, - TC3, 0, 1, 1, PIN_PA19E_TC3_WO1, MUX_PA19E_TC3_WO1, - 0, TCC0, 3, 3, PIN_PA19F_TCC0_WO3, MUX_PA19F_TCC0_WO3); -PIN_TWO_TIMERS(PA17, false, NO_ADC_INPUT, - 0, TCC2, 1, 1, PIN_PA17E_TCC2_WO1, MUX_PA17E_TCC2_WO1, - 0, TCC0, 3, 7, PIN_PA17F_TCC0_WO7, MUX_PA17F_TCC0_WO7); +// S0/S2 S2/S4 S1/S3 S3/S5 +// i2c pins PA08, PA09, PA12, PA13, PA16, PA17, PA22, PA23 +PIN(PA02, true, ADC_POSITIVE_INPUT_PIN0, NO_TIMER, NO_TIMER, NO_SERCOM, \ + NO_SERCOM); +PIN(PB08, true, ADC_POSITIVE_INPUT_PIN8, + TIMER(TC4, 0, 0, 0, PIN_PB08E_TC4_WO0, MUX_PB08E_TC4_WO0), + NO_TIMER, + SERCOM(SERCOM4, 0, PINMUX_PB08D_SERCOM4_PAD0), + NO_SERCOM); +PIN(PB09, true, ADC_POSITIVE_INPUT_PIN9, + TIMER(TC4, 0, 1, 1, PIN_PB09E_TC4_WO1, MUX_PB09E_TC4_WO1), + NO_TIMER, + SERCOM(SERCOM4, 1, PINMUX_PB09D_SERCOM4_PAD1), + NO_SERCOM); +PIN(PA04, true, ADC_POSITIVE_INPUT_PIN4, + TIMER(0, TCC0, 0, 0, PIN_PA04E_TCC0_WO0, MUX_PA04E_TCC0_WO0), + NO_TIMER, + SERCOM(SERCOM0, 0, PINMUX_PA04D_SERCOM0_PAD0), + NO_SERCOM); +PIN(PA05, true, ADC_POSITIVE_INPUT_PIN5, + TIMER(0, TCC0, 1, 1, PIN_PA05E_TCC0_WO1, MUX_PA05E_TCC0_WO1), + NO_TIMER, + SERCOM(SERCOM0, 1, PINMUX_PA05D_SERCOM0_PAD1), + NO_SERCOM); +PIN(PB02, true, ADC_POSITIVE_INPUT_PIN10, + NO_TIMER, + NO_TIMER, + SERCOM(SERCOM5, 0, PINMUX_PB02D_SERCOM5_PAD0), + NO_SERCOM); +PIN(PB11, false, NO_ADC_INPUT, + TIMER(TC5, 0, 1, 1, PIN_PB11E_TC5_WO1, MUX_PB11E_TC5_WO1), + TIMER(0, TCC0, 1, 5, PIN_PB11F_TCC0_WO5, MUX_PB11F_TCC0_WO5), + SERCOM(SERCOM4, 3, PINMUX_PB11D_SERCOM4_PAD3), + NO_SERCOM); +PIN(PB10, false, NO_ADC_INPUT, + TIMER(TC5, 0, 0, 0, PIN_PB10E_TC5_WO0, MUX_PB10E_TC5_WO0), + TIMER(0, TCC0, 0, 4, PIN_PB10F_TCC0_WO4, MUX_PB10F_TCC0_WO4), + SERCOM(SERCOM4, 2, PINMUX_PB10D_SERCOM4_PAD2), + NO_SERCOM); +PIN(PA12, false, NO_ADC_INPUT, + TIMER(0, TCC2, 0, 0, PIN_PA12E_TCC2_WO0, MUX_PA12E_TCC2_WO0), + TIMER(0, TCC0, 2, 6, PIN_PA12F_TCC0_WO6, MUX_PA12F_TCC0_WO6), + SERCOM(SERCOM2, 0, PINMUX_PA12C_SERCOM2_PAD0), + SERCOM(SERCOM4, 0, PINMUX_PA12D_SERCOM4_PAD0)); +PIN(PA11, true, ADC_POSITIVE_INPUT_PIN19, + TIMER(0, TCC1, 1, 1, PIN_PA11E_TCC1_WO1, MUX_PA11E_TCC1_WO1), + TIMER(0, TCC0, 3, 3, PIN_PA11F_TCC0_WO3, MUX_PA11F_TCC0_WO3), + SERCOM(SERCOM0, 3, PINMUX_PA11C_SERCOM0_PAD3), + SERCOM(SERCOM2, 3, PINMUX_PA11D_SERCOM2_PAD3)); +PIN(PA10, true, ADC_POSITIVE_INPUT_PIN18, + TIMER(0, TCC1, 0, 0, PIN_PA10E_TCC1_WO0, MUX_PA10E_TCC1_WO0), + TIMER(0, TCC0, 2, 2, PIN_PA10F_TCC0_WO2, MUX_PA10F_TCC0_WO2), + SERCOM(SERCOM0, 2, PINMUX_PA10C_SERCOM0_PAD2), + SERCOM(SERCOM2, 2, PINMUX_PA10D_SERCOM2_PAD2)); +PIN(PA22, false, NO_ADC_INPUT, + TIMER(TC4, 0, 0, 0, PIN_PA22E_TC4_WO0, MUX_PA22E_TC4_WO0), + TIMER(0, TCC0, 0, 4, PIN_PA22F_TCC0_WO4, MUX_PA22F_TCC0_WO4), + SERCOM(SERCOM3, 0, PINMUX_PA22C_SERCOM3_PAD0), + SERCOM(SERCOM5, 0, PINMUX_PA22D_SERCOM5_PAD0)); +PIN(PA23, false, NO_ADC_INPUT, + TIMER(TC4, 0, 1, 1, PIN_PA23E_TC4_WO1, MUX_PA23E_TC4_WO1), + TIMER(0, TCC0, 1, 5, PIN_PA23F_TCC0_WO5, MUX_PA23F_TCC0_WO5), + SERCOM(SERCOM3, 1, PINMUX_PA23C_SERCOM3_PAD1), + SERCOM(SERCOM5, 1, PINMUX_PA23C_SERCOM3_PAD1)); +PIN(PA15, false, NO_ADC_INPUT, + TIMER(TC3, 0, 1, 1, PIN_PA15E_TC3_WO1, MUX_PA15E_TC3_WO1), + TIMER(0, TCC0, 1, 5, PIN_PA15F_TCC0_WO5, MUX_PA15F_TCC0_WO5), + SERCOM(SERCOM2, 3, PINMUX_PA15C_SERCOM2_PAD3), + SERCOM(SERCOM4, 3, PINMUX_PA15D_SERCOM4_PAD3)); +PIN(PA20, false, NO_ADC_INPUT, + TIMER(0, TCC0, 2, 6, PIN_PA20F_TCC0_WO6, MUX_PA20F_TCC0_WO6), + NO_TIMER, + SERCOM(SERCOM5, 2, PINMUX_PA20C_SERCOM5_PAD2), + SERCOM(SERCOM3, 2, PINMUX_PA20D_SERCOM3_PAD2)); +PIN(PA07, true, ADC_POSITIVE_INPUT_PIN7, + TIMER(0, TCC1, 1, 1, PIN_PA07E_TCC1_WO1, MUX_PA07E_TCC1_WO1), + NO_TIMER, + SERCOM(SERCOM0, 3, PINMUX_PA07D_SERCOM0_PAD3), + NO_SERCOM); +PIN(PA18, false, NO_ADC_INPUT, + TIMER(TC3, 0, 0, 0, PIN_PA18E_TC3_WO0, MUX_PA18E_TC3_WO0), + TIMER(0, TCC0, 2, 2, PIN_PA18F_TCC0_WO2, MUX_PA18F_TCC0_WO2), + SERCOM(SERCOM1, 2, PINMUX_PA18C_SERCOM1_PAD2), + SERCOM(SERCOM3, 2, PINMUX_PA18D_SERCOM3_PAD2)); +PIN(PA16, false, NO_ADC_INPUT, + TIMER(0, TCC2, 0, 0, PIN_PA16E_TCC2_WO0, MUX_PA16E_TCC2_WO0), + TIMER(0, TCC0, 2, 6, PIN_PA16F_TCC0_WO6, MUX_PA16F_TCC0_WO6), + SERCOM(SERCOM1, 0, PINMUX_PA16C_SERCOM1_PAD0), + SERCOM(SERCOM3, 0, PINMUX_PA16D_SERCOM3_PAD0)); +PIN(PA19, false, NO_ADC_INPUT, + TIMER(TC3, 0, 1, 1, PIN_PA19E_TC3_WO1, MUX_PA19E_TC3_WO1), + TIMER(0, TCC0, 3, 3, PIN_PA19F_TCC0_WO3, MUX_PA19F_TCC0_WO3), + SERCOM(SERCOM1, 3, PINMUX_PA19C_SERCOM1_PAD3), + SERCOM(SERCOM3, 3, PINMUX_PA19C_SERCOM1_PAD3)); +PIN(PA17, false, NO_ADC_INPUT, + TIMER(0, TCC2, 1, 1, PIN_PA17E_TCC2_WO1, MUX_PA17E_TCC2_WO1), + TIMER(0, TCC0, 3, 7, PIN_PA17F_TCC0_WO7, MUX_PA17F_TCC0_WO7), + SERCOM(SERCOM1, 1, PINMUX_PA17C_SERCOM1_PAD1), + SERCOM(SERCOM3, 1, PINMUX_PA17D_SERCOM3_PAD1)); STATIC const mp_map_elem_t pin_cpu_pins_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_PA02), (mp_obj_t)&pin_PA02 }, diff --git a/atmel-samd/common-hal/modules/machine.c b/atmel-samd/common-hal/modules/machine.c new file mode 100644 index 000000000..5597f77ed --- /dev/null +++ b/atmel-samd/common-hal/modules/machine.c @@ -0,0 +1,200 @@ +/* + * 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" + + +// Number of times to try to send packet if failed. +#define TIMEOUT 1 + +void mp_hal_i2c_init(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; + // TODO(tannewt): Utilize the secondary sercom if the first is already being + // used. + if (sda->primary_sercom.sercom == 0 || sda->primary_sercom.pad != 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "SDA pin must be on SERCOM pad 0")); + } + if (scl->primary_sercom.sercom == 0 || scl->primary_sercom.pad != 1) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "SCL pin must be on SERCOM pad 1")); + } + if (sda->primary_sercom.sercom != scl->primary_sercom.sercom) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, + "SDA and SCL pins must share a SERCOM")); + } + config_i2c_master.pinmux_pad0 = sda->primary_sercom.pinmux; // SDA + config_i2c_master.pinmux_pad1 = scl->primary_sercom.pinmux; // SCL + config_i2c_master.buffer_timeout = 10000; + + enum status_code status = i2c_master_init(&self->i2c_master_instance, + sda->primary_sercom.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_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; +} diff --git a/atmel-samd/common-hal/modules/machine_types.h b/atmel-samd/common-hal/modules/machine_types.h new file mode 100644 index 000000000..00fe99825 --- /dev/null +++ b/atmel-samd/common-hal/modules/machine_types.h @@ -0,0 +1,80 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Machine is the HAL for low-level, hardware accelerated functions. It is not +// meant to simplify APIs, its only meant to unify them so that other modules +// do not require port specific logic. +// +// This file 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__ + +// 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/sercom/i2c/i2c_master.h" + +#include "py/obj.h" + +typedef struct { + Sercom *const sercom; + uint8_t pad; + uint32_t pinmux; +} pin_sercom_t; + +typedef struct { + Tc *const tc; + Tcc *const tcc; + uint8_t channel; + uint8_t wave_output; + uint32_t pin; + uint32_t mux; +} pin_timer_t; + +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 primary_sercom; + pin_sercom_t secondary_sercom; +} 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; + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_API_MACHINE_TYPES_H__ diff --git a/atmel-samd/modmachine.c b/atmel-samd/modmachine.c index e5ba5ae98..29f6118c6 100644 --- a/atmel-samd/modmachine.c +++ b/atmel-samd/modmachine.c @@ -31,6 +31,8 @@ #include "py/obj.h" #include "py/runtime.h" +#include "shared-bindings/modules/machine.h" + #include "modmachine_adc.h" #include "modmachine_dac.h" #include "modmachine_pin.h" @@ -38,11 +40,13 @@ #include "storage.h" #if MICROPY_PY_MACHINE - +// TODO(tannewt): Add the machine_ prefix to all types so that we don't risk +// conflicting with any port specific implementations. STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) }, { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&adc_type) }, { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&dac_type) }, + { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) }, { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&pwm_type) }, { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&flash_type) }, diff --git a/atmel-samd/modmachine_pin.h b/atmel-samd/modmachine_pin.h index 8ecafe798..820a79246 100644 --- a/atmel-samd/modmachine_pin.h +++ b/atmel-samd/modmachine_pin.h @@ -34,71 +34,50 @@ #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_TWO_TIMERS(p_name, p_has_adc, p_adc_input, p_primary_tc, p_primary_tcc, \ - p_primary_channel, p_primary_wave_output, p_primary_pin, p_primary_mux, \ - p_secondary_tc, p_secondary_tcc, p_secondary_channel, p_secondary_wave_output, \ - p_secondary_pin, p_secondary_mux) \ +#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 = { \ - .tc = p_primary_tc, \ - .tcc = p_primary_tcc, \ - .channel = p_primary_channel, \ - .wave_output = p_primary_wave_output, \ - .pin = p_primary_pin, \ - .mux = p_primary_mux \ - }, \ - .secondary_timer = { \ - .tc = p_secondary_tc, \ - .tcc = p_secondary_tcc, \ - .channel = p_secondary_channel, \ - .wave_output = p_secondary_wave_output, \ - .pin = p_secondary_pin, \ - .mux = p_secondary_mux \ - } \ + .primary_timer = p_primary_timer, \ + .secondary_timer = p_secondary_timer, \ + .primary_sercom = p_primary_sercom, \ + .secondary_sercom = p_secondary_sercom \ } -#define PIN_NO_TIMERS_(p_name, p_has_adc, p_adc_input) \ - PIN_TWO_TIMERS(p_name, p_has_adc, p_adc_input, \ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - -#define PIN_ONE_TIMER_(p_name, p_has_adc, p_adc_input, p_primary_tcc, \ - p_primary_tc, p_primary_channel, p_primary_wave_output, \ - p_primary_pin, p_primary_mux) \ - PIN_TWO_TIMERS(p_name, p_has_adc, p_adc_input, p_primary_tcc, p_primary_tc, \ - p_primary_channel, p_primary_wave_output, p_primary_pin, p_primary_mux, \ - 0, 0, 0, 0, 0, 0) - #define NO_ADC_INPUT (0) #include "mpconfigport.h" #include "py/obj.h" -typedef struct { - Tc *const tc; - Tcc *const tcc; - uint8_t channel; - uint8_t wave_output; - uint32_t pin; - uint32_t mux; -} pin_timer_t; - -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_obj_t; - extern const mp_obj_type_t pin_type; typedef struct { diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h index 549731b31..f4e3de936 100644 --- a/atmel-samd/mpconfigport.h +++ b/atmel-samd/mpconfigport.h @@ -33,22 +33,22 @@ #define MICROPY_PY_BUILTINS_BYTEARRAY (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_ENUMERATE (0) -#define MICROPY_PY_BUILTINS_FILTER (0) +#define MICROPY_PY_BUILTINS_FILTER (1) #define MICROPY_PY_BUILTINS_FROZENSET (0) #define MICROPY_PY_BUILTINS_REVERSED (0) -#define MICROPY_PY_BUILTINS_SET (0) -#define MICROPY_PY_BUILTINS_SLICE (0) -#define MICROPY_PY_BUILTINS_PROPERTY (0) -#define MICROPY_PY_BUILTINS_MIN_MAX (0) -#define MICROPY_PY___FILE__ (0) -#define MICROPY_PY_GC (0) +#define MICROPY_PY_BUILTINS_SET (1) +#define MICROPY_PY_BUILTINS_SLICE (1) +#define MICROPY_PY_BUILTINS_PROPERTY (1) +#define MICROPY_PY_BUILTINS_MIN_MAX (1) +#define MICROPY_PY___FILE__ (1) +#define MICROPY_PY_GC (1) #define MICROPY_PY_ARRAY (1) #define MICROPY_PY_ATTRTUPLE (1) -#define MICROPY_PY_COLLECTIONS (0) -#define MICROPY_PY_MATH (0) -#define MICROPY_PY_CMATH (0) +#define MICROPY_PY_COLLECTIONS (1) +#define MICROPY_PY_MATH (1) +#define MICROPY_PY_CMATH (1) #define MICROPY_PY_IO (0) -#define MICROPY_PY_STRUCT (0) +#define MICROPY_PY_STRUCT (1) #define MICROPY_PY_SYS (0) #define MICROPY_MODULE_FROZEN_MPY (1) #define MICROPY_CPYTHON_COMPAT (0) diff --git a/shared-bindings/modules/machine.c b/shared-bindings/modules/machine.c new file mode 100644 index 000000000..cf21cdefa --- /dev/null +++ b/shared-bindings/modules/machine.c @@ -0,0 +1,285 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// This file contains all of the Python API definitions for the machine module. +// Machine is the HAL for low-level, hardware accelerated functions. It is not +// meant to simplify APIs, its only meant to unify them so that other modules +// do not require port specific logic. + +#include "machine.h" + + +#include "py/runtime.h" + +//| .. currentmodule:: machine +//| +//| class I2C -- a two-wire serial protocol +//| ======================================= +//| +//| I2C is a two-wire protocol for communicating between devices. At the +//| physical level it consists of 2 wires: SCL and SDA, the clock and data lines +//| respectively. +//| +//| I2C objects are created attached to a specific bus. They can be initialised +//| when created, or initialised later on. + +STATIC void machine_i2c_obj_init_helper(machine_i2c_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_scl, ARG_sda, ARG_freq }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 400000} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + // TODO(tannewt): Replace pin_find with a unified version. + const pin_obj_t* scl = pin_find(args[ARG_scl].u_obj); + const pin_obj_t* sda = pin_find(args[ARG_sda].u_obj); + mp_hal_i2c_init(self, scl, sda, args[ARG_freq].u_int); +} + +//| Constructors +//| ------------ +//| .. class:: I2C(scl, sda, \*, freq=400000) +//| +//| Construct and return a new I2C object. +//| See the init method below for a description of the arguments. +STATIC mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + mp_arg_check_num(n_args, n_kw, 0, MP_OBJ_FUN_ARGS_MAX, true); + machine_i2c_obj_t *self = m_new_obj(machine_i2c_obj_t); + self->base.type = &machine_i2c_type; + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); + machine_i2c_obj_init_helper(self, n_args, args, &kw_args); + return (mp_obj_t)self; +} + +//| General Methods +//| --------------- +//| .. method:: I2C.init(scl, sda, \*, freq=400000) +//| +//| Initialise the I2C bus with the given arguments: +//| +//| - `scl` is a pin object for the SCL line +//| - `sda` is a pin object for the SDA line +//| - `freq` is the SCL clock rate +STATIC mp_obj_t machine_i2c_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { + machine_i2c_obj_init_helper(args[0], n_args - 1, args + 1, kw_args); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_init_obj, 1, machine_i2c_obj_init); + +//| .. method:: I2C.scan() +//| +//| Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of +//| those that respond. A device responds if it pulls the SDA line low after +//| its address (including a read bit) is sent on the bus. +STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_obj_t list = mp_obj_new_list(0, NULL); + // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved + for (int addr = 0x08; addr < 0x78; ++addr) { + bool success = mp_hal_i2c_probe(self, addr); + if (success) { + mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); + } + } + return list; +} +MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan); + +//| Standard bus operations +//| ----------------------- +//| +//| The following methods implement the standard I2C master read and write +//| operations that target a given slave device. +//| +//| .. method:: I2C.readfrom(addr, nbytes) +//| +//| Read `nbytes` from the slave specified by `addr`. +//| Returns a `bytes` object with the data read. +STATIC mp_obj_t machine_i2c_readfrom(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t nbytes_in) { + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + vstr_t vstr; + vstr_init_len(&vstr, mp_obj_get_int(nbytes_in)); + mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)vstr.buf, vstr.len); + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_obj, machine_i2c_readfrom); + +//| .. method:: I2C.readfrom_into(addr, buf) +//| +//| Read into `buf` from the slave specified by `addr`. +//| The number of bytes read will be the length of `buf`. +//| +//| On WiPy the return value is the number of bytes read. Otherwise the +//| return value is `None`. +STATIC mp_obj_t machine_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); + mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_into_obj, machine_i2c_readfrom_into); + +//| .. method:: I2C.writeto(addr, buf) +//| +//| Write the bytes from `buf` to the slave specified by `addr`. +STATIC mp_obj_t machine_i2c_writeto(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) { + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); + mp_hal_i2c_write(self, mp_obj_get_int(addr_in), bufinfo.buf, bufinfo.len); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_writeto_obj, machine_i2c_writeto); + +//| Memory operations +//| ----------------- +//| +//| Some I2C devices act as a memory device (or set of registers) that can be +//| read from and written to. In this case there are two addresses associated +//| with an I2C transaction: the slave address and the memory address. The following +//| following methods are convenience functions to communicate with such +//| devices. +//| +//| .. method:: I2C.readfrom_mem(addr, memaddr, nbytes, \*, addrsize=8) +//| +//| Read `nbytes` from the slave specified by `addr` starting from the memory +//| address specified by `memaddr`. +//| The argument `addrsize` specifies the address size in bits (on ESP8266 +//| this argument is not recognised and the address size is always 8 bits). +//| Returns a `bytes` object with the data read. +STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO + }; + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // create the buffer to store data into + vstr_t vstr; + vstr_init_len(&vstr, args[ARG_n].u_int); + + // do the transfer + mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, (uint8_t*)vstr.buf, vstr.len); + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem); + + +//| .. method:: I2C.readfrom_mem_into(addr, memaddr, buf, \*, addrsize=8) +//| +//| Read into `buf` from the slave specified by `addr` starting from the +//| memory address specified by `memaddr`. The number of bytes read is the +//| length of `buf`. +//| The argument `addrsize` specifies the address size in bits (on ESP8266 +//| this argument is not recognised and the address size is always 8 bits). +//| +//| On WiPy the return value is the number of bytes read. Otherwise the +//| return value is `None`. +STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO + }; + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // get the buffer to store data into + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE); + + // do the transfer + mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into); + +//| .. method:: I2C.writeto_mem(addr, memaddr, buf, \*, addrsize=8) +//| +//| Write `buf` to the slave specified by `addr` starting from the +//| memory address specified by `memaddr`. +//| The argument `addrsize` specifies the address size in bits (on ESP8266 +//| this argument is not recognised and the address size is always 8 bits). +//| +//| On WiPy the return value is the number of bytes written. Otherwise the +//| return value is `None`. +STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO + }; + machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + // get the buffer to write the data from + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ); + + // do the transfer + mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem); + +STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_i2c_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&machine_i2c_scan_obj) }, + + // standard bus operations + { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) }, + { MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) }, + + // memory operations + { MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) }, + { MP_ROM_QSTR(MP_QSTR_readfrom_mem_into), MP_ROM_PTR(&machine_i2c_readfrom_mem_into_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeto_mem), MP_ROM_PTR(&machine_i2c_writeto_mem_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(machine_i2c_locals_dict, machine_i2c_locals_dict_table); + +const mp_obj_type_t machine_i2c_type = { + { &mp_type_type }, + .name = MP_QSTR_I2C, + .make_new = machine_i2c_make_new, + .locals_dict = (mp_obj_dict_t*)&machine_i2c_locals_dict, +}; diff --git a/shared-bindings/modules/machine.h b/shared-bindings/modules/machine.h new file mode 100644 index 000000000..9da3d3845 --- /dev/null +++ b/shared-bindings/modules/machine.h @@ -0,0 +1,77 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Scott Shawcroft + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Machine is the HAL for low-level, hardware accelerated functions. It is not +// meant to simplify APIs, its only meant to unify them so that other modules +// do not require port specific logic. +// +// This file includes externs for all functions a port should implement to +// support the machine module. + +#ifndef __MICROPY_INCLUDED_API_MACHINE_H__ +#define __MICROPY_INCLUDED_API_MACHINE_H__ + +#include "py/obj.h" + +// Should include these structs which will be passed through to the port +// implementation: +// * pin_obj_t +// * machine_i2c_obj_t + +// TODO(tannewt): Standardize the type names. + +#include "machine_types.h" + +#include "modmachine_pin.h" + +// Type object used in Python. Should be shared between ports. +extern const mp_obj_type_t machine_i2c_type; + +// Initializes the hardware peripheral. +extern void mp_hal_i2c_init(machine_i2c_obj_t *self, const pin_obj_t * scl, + const pin_obj_t * sda, uint32_t freq); + +// Probe the bus to see if a device acknowledges the given address. +extern bool mp_hal_i2c_probe(machine_i2c_obj_t *self, uint8_t addr); + +// Reads memory of the i2c device picking up where it left off. +extern void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, + uint8_t *data, size_t len); + +// Reads memory of the i2c device starting at memaddr. +extern void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr, + uint16_t memaddr, uint8_t *dest, size_t len); + +extern void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, + uint8_t *data, size_t len); + +// Writes memory of the i2c device starting at memaddr. +extern void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr, + uint16_t memaddr, const uint8_t *src, + size_t len); + + +#endif // __MICROPY_INCLUDED_API_MACHINE_H__ |
