Skip to content

Commit 7cbae3d

Browse files
authored
Merge pull request micropython#2012 from tannewt/remove_i2c_stop_kwarg
Add writeto_then_readfrom to I2C API. Deprecate stop kwarg.
2 parents 42956a6 + 0876d5c commit 7cbae3d

File tree

21 files changed

+214
-93
lines changed

21 files changed

+214
-93
lines changed

lib/utils/buffer_helper.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@
2626

2727
#include "lib/utils/buffer_helper.h"
2828

29-
void normalize_buffer_bounds(int32_t* start, int32_t end, uint32_t* length) {
29+
void normalize_buffer_bounds(int32_t* start, int32_t end, size_t* length) {
3030
if (end < 0) {
3131
end += *length;
32-
} else if (((uint32_t) end) > *length) {
32+
} else if (((size_t) end) > *length) {
3333
end = *length;
3434
}
3535
if (*start < 0) {

lib/utils/buffer_helper.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
#define MICROPY_INCLUDED_LIB_UTILS_BUFFER_HELPER_H
2929

3030
#include <stdint.h>
31+
#include <string.h>
3132

32-
void normalize_buffer_bounds(int32_t* start, int32_t end, uint32_t* length);
33+
void normalize_buffer_bounds(int32_t* start, int32_t end, size_t* length);
3334

3435
#endif // MICROPY_INCLUDED_LIB_UTILS_BUFFER_HELPER_H

ports/atmel-samd/boards/gemma_m0/mpconfigboard.h

-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
#define MICROPY_HW_APA102_MOSI (&pin_PA00)
77
#define MICROPY_HW_APA102_SCK (&pin_PA01)
88

9-
// #define CIRCUITPY_BITBANG_APA102
10-
119
#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA24 | PORT_PA25)
1210
#define MICROPY_PORT_B (0)
1311
#define MICROPY_PORT_C (0)

ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
#define MICROPY_HW_LED_STATUS (&pin_PA17)
55

6-
#define CIRCUITPY_BITBANG_APA102
76
#define MICROPY_HW_APA102_MOSI (&pin_PA01)
87
#define MICROPY_HW_APA102_SCK (&pin_PA00)
98

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

+3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ EXTERNAL_FLASH_DEVICE_COUNT = 2
1212
EXTERNAL_FLASH_DEVICES = "W25Q16FW, GD25Q16C"
1313
LONGINT_IMPL = MPZ
1414

15+
CIRCUITPY_BITBANG_APA102 = 1
16+
17+
CIRCUITPY_BITBANGIO = 0
1518
CIRCUITPY_GAMEPAD = 0
1619
CIRCUITPY_I2CSLAVE = 0
1720
CIRCUITPY_RTC = 0

ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h

-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
1010
#define MICROPY_HW_APA102_SCK (&pin_PB02)
1111

12-
#define CIRCUITPY_BITBANG_APA102
13-
1412
// These are pins not to reset.
1513
// QSPI Data pins
1614
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)

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

+2
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ LONGINT_IMPL = MPZ
1515
CIRCUITPY_PS2IO = 1
1616
# No I2S on SAMD51G
1717
CIRCUITPY_AUDIOBUSIO = 0
18+
19+
CIRCUITPY_BITBANG_APA102 = 1

ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.h

-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
1010
#define MICROPY_HW_APA102_SCK (&pin_PB02)
1111

12-
#define CIRCUITPY_BITBANG_APA102
13-
1412
// These are pins not to reset.
1513
// QSPI Data pins
1614
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)

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

+2
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ LONGINT_IMPL = MPZ
1515
CIRCUITPY_PS2IO = 1
1616
# No I2S on SAMD51G
1717
CIRCUITPY_AUDIOBUSIO = 0
18+
19+
CIRCUITPY_BITBANG_APA102 = 1

ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h

-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
#define MICROPY_HW_APA102_MOSI (&pin_PA00)
55
#define MICROPY_HW_APA102_SCK (&pin_PA01)
66

7-
// #define CIRCUITPY_BITBANG_APA102
8-
97
#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA24 | PORT_PA25)
108
#define MICROPY_PORT_B (0)
119
#define MICROPY_PORT_C (0)

ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h

-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
99
#define MICROPY_HW_APA102_SCK (&pin_PB02)
1010

11-
#define CIRCUITPY_BITBANG_APA102
12-
1311
// These are pins not to reset.
1412
// QSPI Data pins
1513
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)

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

+2
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,5 @@ LONGINT_IMPL = MPZ
1515
CIRCUITPY_PS2IO = 1
1616
# No I2S on SAMD51G
1717
CIRCUITPY_AUDIOBUSIO = 0
18+
19+
CIRCUITPY_BITBANG_APA102 = 1

ports/atmel-samd/common-hal/busio/SPI.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
122122
}
123123
Sercom* potential_sercom = sercom_insts[sercom_index];
124124
if (
125-
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102)
125+
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102
126126
(potential_sercom->SPI.CTRLA.bit.ENABLE != 0 &&
127127
potential_sercom != status_apa102.spi_desc.dev.prvt &&
128128
!apa102_sck_in_use)) {
@@ -181,7 +181,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
181181
// Set up SPI clocks on SERCOM.
182182
samd_peripherals_sercom_clock_init(sercom, sercom_index);
183183

184-
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102)
184+
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102
185185
// if we're re-using the dotstar sercom, make sure it is disabled or the init will fail out
186186
hri_sercomspi_clear_CTRLA_ENABLE_bit(sercom);
187187
#endif

py/circuitpy_defns.mk

+4
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ endif
117117
ifeq ($(CIRCUITPY_BITBANGIO),1)
118118
SRC_PATTERNS += bitbangio/%
119119
endif
120+
# Some builds need bitbang SPI for the dotstar but don't make bitbangio available so include it separately.
121+
ifeq ($(CIRCUITPY_BITBANG_APA102),1)
122+
SRC_PATTERNS += bitbangio/SPI%
123+
endif
120124
ifeq ($(CIRCUITPY_BLEIO),1)
121125
SRC_PATTERNS += bleio/%
122126
endif

py/circuitpy_mpconfig.mk

+6
Original file line numberDiff line numberDiff line change
@@ -278,3 +278,9 @@ ifndef CIRCUITPY_USTACK
278278
CIRCUITPY_USTACK = 0
279279
endif
280280
CFLAGS += -DCIRCUITPY_USTACK=$(CIRCUITPY_USTACK)
281+
282+
283+
ifndef CIRCUITPY_BITBANG_APA102
284+
CIRCUITPY_BITBANG_APA102 = 0
285+
endif
286+
CFLAGS += -DCIRCUITPY_BITBANG_APA102=$(CIRCUITPY_BITBANG_APA102)

shared-bindings/bitbangio/I2C.c

+90-33
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,23 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock);
175175
//| :param int start: Index to start writing at
176176
//| :param int end: Index to write up to but not include
177177
//|
178+
// Shared arg parsing for readfrom_into and writeto_then_readfrom.
179+
STATIC void readfrom(bitbangio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end) {
180+
mp_buffer_info_t bufinfo;
181+
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE);
182+
183+
size_t length = bufinfo.len;
184+
normalize_buffer_bounds(&start, end, &length);
185+
if (length == 0) {
186+
mp_raise_ValueError(translate("Buffer must be at least length 1"));
187+
}
188+
189+
uint8_t status = shared_module_bitbangio_i2c_read(self, address, ((uint8_t*)bufinfo.buf) + start, length);
190+
if (status != 0) {
191+
mp_raise_OSError(status);
192+
}
193+
}
194+
178195
STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
179196
enum { ARG_address, ARG_buffer, ARG_start, ARG_end };
180197
static const mp_arg_t allowed_args[] = {
@@ -185,33 +202,21 @@ STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a
185202
};
186203
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
187204
check_for_deinit(self);
205+
check_lock(self);
188206
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
189207
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
190-
check_lock(self);
191-
mp_buffer_info_t bufinfo;
192-
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);
193208

194-
int32_t start = args[ARG_start].u_int;
195-
uint32_t length = bufinfo.len;
196-
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
197-
if (length == 0) {
198-
mp_raise_ValueError(translate("Buffer must be at least length 1"));
199-
}
200-
uint8_t status = shared_module_bitbangio_i2c_read(self,
201-
args[ARG_address].u_int,
202-
((uint8_t*)bufinfo.buf) + start,
203-
length);
204-
if (status != 0) {
205-
mp_raise_OSError(status);
206-
}
209+
readfrom(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
210+
args[ARG_end].u_int);
207211
return mp_const_none;
208212
}
209213
MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_readfrom_into);
210214

211215
//| .. method:: writeto(address, buffer, *, start=0, end=None, stop=True)
212216
//|
213-
//| Write the bytes from ``buffer`` to the slave specified by ``address``.
214-
//| Transmits a stop bit if ``stop`` is set.
217+
//| Write the bytes from ``buffer`` to the slave specified by ``address`` and then transmits a
218+
//| stop bit. Use `writeto_then_readfrom` when needing a write, no stop and repeated start
219+
//| before a read.
215220
//|
216221
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
217222
//| as if ``buffer[start:end]``. This will not cause an allocation like
@@ -224,9 +229,27 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_rea
224229
//| :param bytearray buffer: buffer containing the bytes to write
225230
//| :param int start: Index to start writing from
226231
//| :param int end: Index to read up to but not include
227-
//| :param bool stop: If true, output an I2C stop condition after the
228-
//| buffer is written
232+
//| :param bool stop: If true, output an I2C stop condition after the buffer is written.
233+
//| Deprecated. Will be removed in 6.x and act as stop=True.
229234
//|
235+
// Shared arg parsing for writeto and writeto_then_readfrom.
236+
STATIC void writeto(bitbangio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end, bool stop) {
237+
// get the buffer to write the data from
238+
mp_buffer_info_t bufinfo;
239+
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ);
240+
241+
size_t length = bufinfo.len;
242+
normalize_buffer_bounds(&start, end, &length);
243+
244+
// do the transfer
245+
uint8_t status = shared_module_bitbangio_i2c_write(self, address,
246+
((uint8_t*) bufinfo.buf) + start, length,
247+
stop);
248+
if (status != 0) {
249+
mp_raise_OSError(status);
250+
}
251+
}
252+
230253
STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
231254
enum { ARG_address, ARG_buffer, ARG_start, ARG_end, ARG_stop };
232255
static const mp_arg_t allowed_args[] = {
@@ -242,23 +265,56 @@ STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, m
242265
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
243266
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
244267

245-
// get the buffer to write the data from
246-
mp_buffer_info_t bufinfo;
247-
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
268+
writeto(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
269+
args[ARG_end].u_int, args[ARG_stop].u_bool);
270+
return mp_const_none;
271+
}
272+
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_writeto);
248273

249-
int32_t start = args[ARG_start].u_int;
250-
uint32_t length = bufinfo.len;
251-
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
252274

253-
// do the transfer
254-
uint8_t status = shared_module_bitbangio_i2c_write(self, args[ARG_address].u_int,
255-
((uint8_t*) bufinfo.buf) + start, length, args[ARG_stop].u_bool);
256-
if (status != 0) {
257-
mp_raise_OSError(status);
258-
}
275+
//| .. method:: writeto_then_readfrom(address, out_buffer, in_buffer, *, out_start=0, out_end=None, in_start=0, in_end=None)
276+
//|
277+
//| Write the bytes from ``out_buffer`` to the slave specified by ``address``, generate no stop
278+
//| bit, generate a repeated start and read into ``in_buffer``. ``out_buffer`` and
279+
//| ``in_buffer`` can be the same buffer because they are used sequentially.
280+
//|
281+
//| If ``start`` or ``end`` is provided, then the corresponding buffer will be sliced
282+
//| as if ``buffer[start:end]``. This will not cause an allocation like ``buf[start:end]``
283+
//| will so it saves memory.
284+
//|
285+
//| :param int address: 7-bit device address
286+
//| :param bytearray out_buffer: buffer containing the bytes to write
287+
//| :param bytearray in_buffer: buffer to write into
288+
//| :param int out_start: Index to start writing from
289+
//| :param int out_end: Index to read up to but not include. Defaults to ``len(buffer)``
290+
//| :param int in_start: Index to start writing at
291+
//| :param int in_end: Index to write up to but not include. Defaults to ``len(buffer)``
292+
//|
293+
STATIC mp_obj_t bitbangio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
294+
enum { ARG_address, ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
295+
static const mp_arg_t allowed_args[] = {
296+
{ MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
297+
{ MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
298+
{ MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
299+
{ MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
300+
{ MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
301+
{ MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
302+
{ MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
303+
};
304+
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
305+
check_for_deinit(self);
306+
check_lock(self);
307+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
308+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
309+
310+
writeto(self, args[ARG_address].u_int, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int,
311+
args[ARG_out_end].u_int, false);
312+
readfrom(self, args[ARG_address].u_int, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int,
313+
args[ARG_in_end].u_int);
314+
259315
return mp_const_none;
260316
}
261-
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_writeto);
317+
MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_then_readfrom_obj, 3, bitbangio_i2c_writeto_then_readfrom);
262318

263319
STATIC const mp_rom_map_elem_t bitbangio_i2c_locals_dict_table[] = {
264320
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&bitbangio_i2c_deinit_obj) },
@@ -271,6 +327,7 @@ STATIC const mp_rom_map_elem_t bitbangio_i2c_locals_dict_table[] = {
271327

272328
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&bitbangio_i2c_writeto_obj) },
273329
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&bitbangio_i2c_readfrom_into_obj) },
330+
{ MP_ROM_QSTR(MP_QSTR_writeto_then_readfrom), MP_ROM_PTR(&bitbangio_i2c_writeto_then_readfrom_obj) },
274331
};
275332

276333
STATIC MP_DEFINE_CONST_DICT(bitbangio_i2c_locals_dict, bitbangio_i2c_locals_dict_table);

shared-bindings/bitbangio/SPI.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,13 @@ STATIC mp_obj_t bitbangio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_
275275
mp_buffer_info_t buf_out_info;
276276
mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ);
277277
int32_t out_start = args[ARG_out_start].u_int;
278-
uint32_t out_length = buf_out_info.len;
278+
size_t out_length = buf_out_info.len;
279279
normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length);
280280

281281
mp_buffer_info_t buf_in_info;
282282
mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE);
283283
int32_t in_start = args[ARG_in_start].u_int;
284-
uint32_t in_length = buf_in_info.len;
284+
size_t in_length = buf_in_info.len;
285285
normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length);
286286

287287
if (out_length != in_length) {

0 commit comments

Comments
 (0)