Skip to content

Commit a7b3de4

Browse files
add SPITarget interface (HAL still unimplemented)
1 parent 2ba0b56 commit a7b3de4

File tree

11 files changed

+608
-1
lines changed

11 files changed

+608
-1
lines changed

docs/porting.rst

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ as a natural "TODO" list. An example minimal build list is shown below:
7272
CIRCUITPY_FRAMEBUFFERIO = 0
7373
CIRCUITPY_FREQUENCYIO = 0
7474
CIRCUITPY_I2CTARGET = 0
75+
CIRCUITPY_SPITARGET = 0
7576
# Requires SPI, PulseIO (stub ok):
7677
CIRCUITPY_DISPLAYIO = 0
7778

ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ CIRCUITPY_BLEIO_HCI = 0
2222
CIRCUITPY_DISPLAYIO = 0
2323
CIRCUITPY_FRAMEBUFFERIO = 0
2424
CIRCUITPY_KEYPAD = 0
25-
CIRCUITPY_I2CTARGET = 0
2625
CIRCUITPY_TOUCHIO = 0
2726
CIRCUITPY_RGBMATRIX = 0
2827
CIRCUITPY_PS2IO = 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,257 @@
1+
// /*
2+
// * This file is part of the MicroPython project, http://micropython.org/
3+
// *
4+
// * The MIT License (MIT)
5+
// *
6+
// * Copyright (c) 2018 Noralf Trønnes
7+
// *
8+
// * Permission is hereby granted, free of charge, to any person obtaining a copy
9+
// * of this software and associated documentation files (the "Software"), to deal
10+
// * in the Software without restriction, including without limitation the rights
11+
// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
// * copies of the Software, and to permit persons to whom the Software is
13+
// * furnished to do so, subject to the following conditions:
14+
// *
15+
// * The above copyright notice and this permission notice shall be included in
16+
// * all copies or substantial portions of the Software.
17+
// *
18+
// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
// * THE SOFTWARE.
25+
// */
26+
27+
// #include "shared-bindings/i2ctarget/I2CTarget.h"
28+
// #include "shared-bindings/microcontroller/Pin.h"
29+
// #include "common-hal/busio/I2C.h"
30+
31+
// #include "shared/runtime/interrupt_char.h"
32+
// #include "py/mperrno.h"
33+
// #include "py/mphal.h"
34+
// #include "py/runtime.h"
35+
36+
// #include "hal/include/hal_gpio.h"
37+
// #include "peripherals/samd/sercom.h"
38+
39+
// void common_hal_i2ctarget_i2c_target_construct(i2ctarget_i2c_target_obj_t *self,
40+
// const mcu_pin_obj_t *scl, const mcu_pin_obj_t *sda,
41+
// uint8_t *addresses, unsigned int num_addresses, bool smbus) {
42+
// uint8_t sercom_index;
43+
// uint32_t sda_pinmux, scl_pinmux;
44+
// Sercom *sercom = samd_i2c_get_sercom(scl, sda, &sercom_index, &sda_pinmux, &scl_pinmux);
45+
// if (sercom == NULL) {
46+
// raise_ValueError_invalid_pins();
47+
// }
48+
// self->sercom = sercom;
49+
50+
// gpio_set_pin_function(sda->number, GPIO_PIN_FUNCTION_OFF);
51+
// gpio_set_pin_function(scl->number, GPIO_PIN_FUNCTION_OFF);
52+
// gpio_set_pin_function(sda->number, sda_pinmux);
53+
// gpio_set_pin_function(scl->number, scl_pinmux);
54+
55+
// self->sda_pin = sda->number;
56+
// self->scl_pin = scl->number;
57+
// claim_pin(sda);
58+
// claim_pin(scl);
59+
60+
// samd_peripherals_sercom_clock_init(sercom, sercom_index);
61+
62+
// #ifdef SAM_D5X_E5X
63+
// sercom->I2CS.CTRLC.bit.SDASETUP = 0x08;
64+
// #endif
65+
66+
// sercom->I2CS.CTRLA.bit.SWRST = 1;
67+
// while (sercom->I2CS.CTRLA.bit.SWRST || sercom->I2CS.SYNCBUSY.bit.SWRST) {
68+
// }
69+
70+
// sercom->I2CS.CTRLB.bit.AACKEN = 0; // Automatic acknowledge is disabled.
71+
72+
// if (num_addresses == 1) {
73+
// sercom->I2CS.CTRLB.bit.AMODE = 0x0; // MASK
74+
// sercom->I2CS.ADDR.bit.ADDR = addresses[0];
75+
// sercom->I2CS.ADDR.bit.ADDRMASK = 0x00; // Match exact address
76+
// } else if (num_addresses == 2) {
77+
// sercom->I2CS.CTRLB.bit.AMODE = 0x1; // 2_ADDRS
78+
// sercom->I2CS.ADDR.bit.ADDR = addresses[0];
79+
// sercom->I2CS.ADDR.bit.ADDRMASK = addresses[1];
80+
// } else {
81+
// uint32_t combined = 0; // all addresses OR'ed
82+
// uint32_t differ = 0; // bits that differ between addresses
83+
// for (unsigned int i = 0; i < num_addresses; i++) {
84+
// combined |= addresses[i];
85+
// differ |= addresses[0] ^ addresses[i];
86+
// }
87+
// sercom->I2CS.CTRLB.bit.AMODE = 0x0; // MASK
88+
// sercom->I2CS.ADDR.bit.ADDR = combined;
89+
// sercom->I2CS.ADDR.bit.ADDRMASK = differ;
90+
// }
91+
// self->addresses = addresses;
92+
// self->num_addresses = num_addresses;
93+
94+
// if (smbus) {
95+
// sercom->I2CS.CTRLA.bit.LOWTOUTEN = 1; // Errata 12003
96+
// sercom->I2CS.CTRLA.bit.SEXTTOEN = 1; // SCL Low Extend/Cumulative Time-Out 25ms
97+
// }
98+
// sercom->I2CS.CTRLA.bit.SCLSM = 0; // Clock stretch before ack
99+
// sercom->I2CS.CTRLA.bit.MODE = 0x04; // Device mode
100+
// sercom->I2CS.CTRLA.bit.ENABLE = 1;
101+
// }
102+
103+
// bool common_hal_i2ctarget_i2c_target_deinited(i2ctarget_i2c_target_obj_t *self) {
104+
// return self->sda_pin == NO_PIN;
105+
// }
106+
107+
// void common_hal_i2ctarget_i2c_target_deinit(i2ctarget_i2c_target_obj_t *self) {
108+
// if (common_hal_i2ctarget_i2c_target_deinited(self)) {
109+
// return;
110+
// }
111+
112+
// self->sercom->I2CS.CTRLA.bit.ENABLE = 0;
113+
114+
// reset_pin_number(self->sda_pin);
115+
// reset_pin_number(self->scl_pin);
116+
// self->sda_pin = NO_PIN;
117+
// self->scl_pin = NO_PIN;
118+
// }
119+
120+
// static int i2c_target_check_error(i2ctarget_i2c_target_obj_t *self, bool raise) {
121+
// if (!self->sercom->I2CS.INTFLAG.bit.ERROR) {
122+
// return 0;
123+
// }
124+
125+
// int err = MP_EIO;
126+
127+
// if (self->sercom->I2CS.STATUS.bit.LOWTOUT || self->sercom->I2CS.STATUS.bit.SEXTTOUT) {
128+
// err = MP_ETIMEDOUT;
129+
// }
130+
131+
// self->sercom->I2CS.INTFLAG.reg = SERCOM_I2CS_INTFLAG_ERROR; // Clear flag
132+
133+
// if (raise) {
134+
// mp_raise_OSError(err);
135+
// }
136+
// return -err;
137+
// }
138+
139+
// int common_hal_i2ctarget_i2c_target_is_addressed(i2ctarget_i2c_target_obj_t *self, uint8_t *address, bool *is_read, bool *is_restart) {
140+
// int err = i2c_target_check_error(self, false);
141+
// if (err) {
142+
// return err;
143+
// }
144+
145+
// if (!self->sercom->I2CS.INTFLAG.bit.AMATCH) {
146+
// return 0;
147+
// }
148+
149+
// self->writing = false;
150+
151+
// *address = self->sercom->I2CS.DATA.reg >> 1;
152+
// *is_read = self->sercom->I2CS.STATUS.bit.DIR;
153+
// *is_restart = self->sercom->I2CS.STATUS.bit.SR;
154+
155+
// for (unsigned int i = 0; i < self->num_addresses; i++) {
156+
// if (*address == self->addresses[i]) {
157+
// common_hal_i2ctarget_i2c_target_ack(self, true);
158+
// return 1;
159+
// }
160+
// }
161+
162+
// // This should clear AMATCH, but it doesn't...
163+
// common_hal_i2ctarget_i2c_target_ack(self, false);
164+
// return 0;
165+
// }
166+
167+
// int common_hal_i2ctarget_i2c_target_read_byte(i2ctarget_i2c_target_obj_t *self, uint8_t *data) {
168+
// for (int t = 0; t < 100 && !self->sercom->I2CS.INTFLAG.reg; t++) {
169+
// mp_hal_delay_us(10);
170+
// }
171+
172+
// i2c_target_check_error(self, true);
173+
174+
// if (!self->sercom->I2CS.INTFLAG.bit.DRDY ||
175+
// self->sercom->I2CS.INTFLAG.bit.PREC ||
176+
// self->sercom->I2CS.INTFLAG.bit.AMATCH) {
177+
// return 0;
178+
// }
179+
180+
// *data = self->sercom->I2CS.DATA.reg;
181+
// return 1;
182+
// }
183+
184+
// int common_hal_i2ctarget_i2c_target_write_byte(i2ctarget_i2c_target_obj_t *self, uint8_t data) {
185+
// for (int t = 0; !self->sercom->I2CS.INTFLAG.reg && t < 100; t++) {
186+
// mp_hal_delay_us(10);
187+
// }
188+
189+
// i2c_target_check_error(self, true);
190+
191+
// if (self->sercom->I2CS.INTFLAG.bit.PREC) {
192+
// return 0;
193+
// }
194+
195+
// // RXNACK can carry over from the previous transfer
196+
// if (self->writing && self->sercom->I2CS.STATUS.bit.RXNACK) {
197+
// return 0;
198+
// }
199+
200+
// self->writing = true;
201+
202+
// if (!self->sercom->I2CS.INTFLAG.bit.DRDY) {
203+
// return 0;
204+
// }
205+
206+
// self->sercom->I2CS.DATA.bit.DATA = data; // Send data
207+
208+
// return 1;
209+
// }
210+
211+
// void common_hal_i2ctarget_i2c_target_ack(i2ctarget_i2c_target_obj_t *self, bool ack) {
212+
// self->sercom->I2CS.CTRLB.bit.ACKACT = !ack;
213+
// self->sercom->I2CS.CTRLB.bit.CMD = 0x03;
214+
// }
215+
216+
// void common_hal_i2ctarget_i2c_target_close(i2ctarget_i2c_target_obj_t *self) {
217+
// for (int t = 0; !self->sercom->I2CS.INTFLAG.reg && t < 100; t++) {
218+
// mp_hal_delay_us(10);
219+
// }
220+
221+
// if (self->sercom->I2CS.INTFLAG.bit.AMATCH || !self->sercom->I2CS.STATUS.bit.CLKHOLD) {
222+
// return;
223+
// }
224+
225+
// if (!self->sercom->I2CS.STATUS.bit.DIR) {
226+
// common_hal_i2ctarget_i2c_target_ack(self, false);
227+
// } else {
228+
// int i = 0;
229+
// while (self->sercom->I2CS.INTFLAG.reg == SERCOM_I2CS_INTFLAG_DRDY) {
230+
// if (mp_hal_is_interrupted()) {
231+
// return;
232+
// }
233+
234+
// self->sercom->I2CS.DATA.bit.DATA = 0xff; // Send dummy byte
235+
236+
// // Wait for a result (if any).
237+
// // test_byte_word.py::TestWord::test_write_seq leaves us with no INTFLAGs set in some of the tests
238+
// for (int t = 0; !self->sercom->I2CS.INTFLAG.reg && t < 100; t++) {
239+
// mp_hal_delay_us(10);
240+
// }
241+
242+
// if (++i > 1000) { // Avoid getting stuck "forever"
243+
// mp_raise_OSError(MP_EIO);
244+
// }
245+
// }
246+
// }
247+
248+
// if (self->sercom->I2CS.INTFLAG.bit.AMATCH) {
249+
// return;
250+
// }
251+
252+
// if (self->sercom->I2CS.STATUS.bit.CLKHOLD) {
253+
// // Unable to release the clock.
254+
// // The device might have to be re-initialized to get unstuck.
255+
// mp_raise_OSError(MP_EIO);
256+
// }
257+
// }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// /*
2+
// * This file is part of the MicroPython project, http://micropython.org/
3+
// *
4+
// * The MIT License (MIT)
5+
// *
6+
// * Copyright (c) 2018 Noralf Trønnes
7+
// *
8+
// * Permission is hereby granted, free of charge, to any person obtaining a copy
9+
// * of this software and associated documentation files (the "Software"), to deal
10+
// * in the Software without restriction, including without limitation the rights
11+
// * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
// * copies of the Software, and to permit persons to whom the Software is
13+
// * furnished to do so, subject to the following conditions:
14+
// *
15+
// * The above copyright notice and this permission notice shall be included in
16+
// * all copies or substantial portions of the Software.
17+
// *
18+
// * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
// * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
// * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
// * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
// * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
// * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
// * THE SOFTWARE.
25+
// */
26+
27+
// #ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_I2C_TARGET_H
28+
// #define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_I2C_TARGET_H
29+
30+
// #include "common-hal/microcontroller/Pin.h"
31+
// #include "py/obj.h"
32+
33+
// typedef struct {
34+
// mp_obj_base_t base;
35+
36+
// uint8_t *addresses;
37+
// unsigned int num_addresses;
38+
39+
// Sercom *sercom;
40+
// uint8_t scl_pin;
41+
// uint8_t sda_pin;
42+
// bool writing;
43+
// } i2ctarget_i2c_target_obj_t;
44+
45+
// #endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_I2C_TARGET_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// No spitarget module functions.

ports/atmel-samd/mpconfigport.mk

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ CIRCUITPY_OS_GETENV ?= 0
4646
CIRCUITPY_PIXELMAP ?= 0
4747
CIRCUITPY_RE ?= 0
4848
CIRCUITPY_SDCARDIO ?= 0
49+
CIRCUITPY_SPITARGET ?= 0
4950
CIRCUITPY_SYNTHIO ?= 0
5051
CIRCUITPY_TOUCHIO_USE_NATIVE ?= 1
5152
CIRCUITPY_TRACEBACK ?= 0
@@ -105,6 +106,7 @@ CIRCUITPY_FRAMEBUFFERIO ?= $(CIRCUITPY_FULL_BUILD)
105106
CIRCUITPY_PS2IO ?= 1
106107
CIRCUITPY_RGBMATRIX ?= $(CIRCUITPY_FRAMEBUFFERIO)
107108
CIRCUITPY_SAMD ?= 1
109+
CIRCUITPY_SPITARGET ?= 1
108110
CIRCUITPY_SYNTHIO_MAX_CHANNELS = 12
109111
CIRCUITPY_ULAB_OPTIMIZE_SIZE ?= 1
110112
CIRCUITPY_WATCHDOG ?= 1

py/circuitpy_defns.mk

+5
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ endif
351351
ifeq ($(CIRCUITPY_SOCKETPOOL),1)
352352
SRC_PATTERNS += socketpool/%
353353
endif
354+
ifeq ($(CIRCUITPY_SPITARGET),1)
355+
SRC_PATTERNS += spitarget/%
356+
endif
354357
ifeq ($(CIRCUITPY_SSL),1)
355358
SRC_PATTERNS += ssl/%
356359
endif
@@ -516,6 +519,8 @@ SRC_COMMON_HAL_ALL = \
516519
socketpool/__init__.c \
517520
socketpool/SocketPool.c \
518521
socketpool/Socket.c \
522+
spitarget/SPITarget.c \
523+
spitarget/__init__.c \
519524
supervisor/Runtime.c \
520525
supervisor/__init__.c \
521526
usb_host/__init__.c \

py/circuitpy_mpconfig.mk

+3
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,9 @@ CFLAGS += -DCIRCUITPY_SKIP_SAFE_MODE_WAIT=$(CIRCUITPY_SKIP_SAFE_MODE_WAIT)
476476
CIRCUITPY_SOCKETPOOL ?= $(CIRCUITPY_WIFI)
477477
CFLAGS += -DCIRCUITPY_SOCKETPOOL=$(CIRCUITPY_SOCKETPOOL)
478478

479+
CIRCUITPY_SPITARGET ?= 0
480+
CFLAGS += -DCIRCUITPY_SPITARGET=$(CIRCUITPY_SPITARGET)
481+
479482
CIRCUITPY_SSL ?= $(CIRCUITPY_WIFI)
480483
CFLAGS += -DCIRCUITPY_SSL=$(CIRCUITPY_SSL)
481484

0 commit comments

Comments
 (0)