Skip to content

Add writeto_then_readfrom to I2C API. Deprecate stop kwarg. #2012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/utils/buffer_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@

#include "lib/utils/buffer_helper.h"

void normalize_buffer_bounds(int32_t* start, int32_t end, uint32_t* length) {
void normalize_buffer_bounds(int32_t* start, int32_t end, size_t* length) {
if (end < 0) {
end += *length;
} else if (((uint32_t) end) > *length) {
} else if (((size_t) end) > *length) {
end = *length;
}
if (*start < 0) {
Expand Down
3 changes: 2 additions & 1 deletion lib/utils/buffer_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
#define MICROPY_INCLUDED_LIB_UTILS_BUFFER_HELPER_H

#include <stdint.h>
#include <string.h>

void normalize_buffer_bounds(int32_t* start, int32_t end, uint32_t* length);
void normalize_buffer_bounds(int32_t* start, int32_t end, size_t* length);

#endif // MICROPY_INCLUDED_LIB_UTILS_BUFFER_HELPER_H
2 changes: 0 additions & 2 deletions ports/atmel-samd/boards/gemma_m0/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PA00)
#define MICROPY_HW_APA102_SCK (&pin_PA01)

// #define CIRCUITPY_BITBANG_APA102

#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA24 | PORT_PA25)
#define MICROPY_PORT_B (0)
#define MICROPY_PORT_C (0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#define MICROPY_HW_LED_STATUS (&pin_PA17)

#define CIRCUITPY_BITBANG_APA102
#define MICROPY_HW_APA102_MOSI (&pin_PA01)
#define MICROPY_HW_APA102_SCK (&pin_PA00)

Expand Down
3 changes: 3 additions & 0 deletions ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q16FW, GD25Q16C"
LONGINT_IMPL = MPZ

CIRCUITPY_BITBANG_APA102 = 1

CIRCUITPY_BITBANGIO = 0
CIRCUITPY_GAMEPAD = 0
CIRCUITPY_I2CSLAVE = 0
CIRCUITPY_RTC = 0
Expand Down
2 changes: 0 additions & 2 deletions ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
#define MICROPY_HW_APA102_SCK (&pin_PB02)

#define CIRCUITPY_BITBANG_APA102

// These are pins not to reset.
// QSPI Data pins
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
Expand Down
2 changes: 2 additions & 0 deletions ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ LONGINT_IMPL = MPZ
CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0

CIRCUITPY_BITBANG_APA102 = 1
2 changes: 0 additions & 2 deletions ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
#define MICROPY_HW_APA102_SCK (&pin_PB02)

#define CIRCUITPY_BITBANG_APA102

// These are pins not to reset.
// QSPI Data pins
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
Expand Down
2 changes: 2 additions & 0 deletions ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ LONGINT_IMPL = MPZ
CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0

CIRCUITPY_BITBANG_APA102 = 1
2 changes: 0 additions & 2 deletions ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PA00)
#define MICROPY_HW_APA102_SCK (&pin_PA01)

// #define CIRCUITPY_BITBANG_APA102

#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA24 | PORT_PA25)
#define MICROPY_PORT_B (0)
#define MICROPY_PORT_C (0)
Expand Down
2 changes: 0 additions & 2 deletions ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
#define MICROPY_HW_APA102_MOSI (&pin_PB03)
#define MICROPY_HW_APA102_SCK (&pin_PB02)

#define CIRCUITPY_BITBANG_APA102

// These are pins not to reset.
// QSPI Data pins
#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
Expand Down
2 changes: 2 additions & 0 deletions ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ LONGINT_IMPL = MPZ
CIRCUITPY_PS2IO = 1
# No I2S on SAMD51G
CIRCUITPY_AUDIOBUSIO = 0

CIRCUITPY_BITBANG_APA102 = 1
4 changes: 2 additions & 2 deletions ports/atmel-samd/common-hal/busio/SPI.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
}
Sercom* potential_sercom = sercom_insts[sercom_index];
if (
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102)
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102
(potential_sercom->SPI.CTRLA.bit.ENABLE != 0 &&
potential_sercom != status_apa102.spi_desc.dev.prvt &&
!apa102_sck_in_use)) {
Expand Down Expand Up @@ -181,7 +181,7 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
// Set up SPI clocks on SERCOM.
samd_peripherals_sercom_clock_init(sercom, sercom_index);

#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !defined(CIRCUITPY_BITBANG_APA102)
#if defined(MICROPY_HW_APA102_SCK) && defined(MICROPY_HW_APA102_MOSI) && !CIRCUITPY_BITBANG_APA102
// if we're re-using the dotstar sercom, make sure it is disabled or the init will fail out
hri_sercomspi_clear_CTRLA_ENABLE_bit(sercom);
#endif
Expand Down
4 changes: 4 additions & 0 deletions py/circuitpy_defns.mk
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ endif
ifeq ($(CIRCUITPY_BITBANGIO),1)
SRC_PATTERNS += bitbangio/%
endif
# Some builds need bitbang SPI for the dotstar but don't make bitbangio available so include it separately.
ifeq ($(CIRCUITPY_BITBANG_APA102),1)
SRC_PATTERNS += bitbangio/SPI%
endif
ifeq ($(CIRCUITPY_BLEIO),1)
SRC_PATTERNS += bleio/%
endif
Expand Down
6 changes: 6 additions & 0 deletions py/circuitpy_mpconfig.mk
Original file line number Diff line number Diff line change
Expand Up @@ -278,3 +278,9 @@ ifndef CIRCUITPY_USTACK
CIRCUITPY_USTACK = 0
endif
CFLAGS += -DCIRCUITPY_USTACK=$(CIRCUITPY_USTACK)


ifndef CIRCUITPY_BITBANG_APA102
CIRCUITPY_BITBANG_APA102 = 0
endif
CFLAGS += -DCIRCUITPY_BITBANG_APA102=$(CIRCUITPY_BITBANG_APA102)
123 changes: 90 additions & 33 deletions shared-bindings/bitbangio/I2C.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,23 @@ MP_DEFINE_CONST_FUN_OBJ_1(bitbangio_i2c_unlock_obj, bitbangio_i2c_obj_unlock);
//| :param int start: Index to start writing at
//| :param int end: Index to write up to but not include
//|
// Shared arg parsing for readfrom_into and writeto_then_readfrom.
STATIC void readfrom(bitbangio_i2c_obj_t *self, mp_int_t address, mp_obj_t buffer, int32_t start, mp_int_t end) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_WRITE);

size_t length = bufinfo.len;
normalize_buffer_bounds(&start, end, &length);
if (length == 0) {
mp_raise_ValueError(translate("Buffer must be at least length 1"));
}

uint8_t status = shared_module_bitbangio_i2c_read(self, address, ((uint8_t*)bufinfo.buf) + start, length);
if (status != 0) {
mp_raise_OSError(status);
}
}

STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_buffer, ARG_start, ARG_end };
static const mp_arg_t allowed_args[] = {
Expand All @@ -185,33 +202,21 @@ STATIC mp_obj_t bitbangio_i2c_readfrom_into(size_t n_args, const mp_obj_t *pos_a
};
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
check_lock(self);
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);
check_lock(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buffer].u_obj, &bufinfo, MP_BUFFER_WRITE);

int32_t start = args[ARG_start].u_int;
uint32_t length = bufinfo.len;
normalize_buffer_bounds(&start, args[ARG_end].u_int, &length);
if (length == 0) {
mp_raise_ValueError(translate("Buffer must be at least length 1"));
}
uint8_t status = shared_module_bitbangio_i2c_read(self,
args[ARG_address].u_int,
((uint8_t*)bufinfo.buf) + start,
length);
if (status != 0) {
mp_raise_OSError(status);
}
readfrom(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
args[ARG_end].u_int);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_readfrom_into);

//| .. method:: writeto(address, buffer, *, start=0, end=None, stop=True)
//|
//| Write the bytes from ``buffer`` to the slave specified by ``address``.
//| Transmits a stop bit if ``stop`` is set.
//| Write the bytes from ``buffer`` to the slave specified by ``address`` and then transmits a
//| stop bit. Use `writeto_then_readfrom` when needing a write, no stop and repeated start
//| before a read.
//|
//| If ``start`` or ``end`` is provided, then the buffer will be sliced
//| as if ``buffer[start:end]``. This will not cause an allocation like
Expand All @@ -224,9 +229,27 @@ MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_readfrom_into_obj, 3, bitbangio_i2c_rea
//| :param bytearray buffer: buffer containing the bytes to write
//| :param int start: Index to start writing from
//| :param int end: Index to read up to but not include
//| :param bool stop: If true, output an I2C stop condition after the
//| buffer is written
//| :param bool stop: If true, output an I2C stop condition after the buffer is written.
//| Deprecated. Will be removed in 6.x and act as stop=True.
//|
// Shared arg parsing for writeto and writeto_then_readfrom.
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) {
// get the buffer to write the data from
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buffer, &bufinfo, MP_BUFFER_READ);

size_t length = bufinfo.len;
normalize_buffer_bounds(&start, end, &length);

// do the transfer
uint8_t status = shared_module_bitbangio_i2c_write(self, address,
((uint8_t*) bufinfo.buf) + start, length,
stop);
if (status != 0) {
mp_raise_OSError(status);
}
}

STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_buffer, ARG_start, ARG_end, ARG_stop };
static const mp_arg_t allowed_args[] = {
Expand All @@ -242,23 +265,56 @@ STATIC mp_obj_t bitbangio_i2c_writeto(size_t n_args, const mp_obj_t *pos_args, m
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_buffer].u_obj, &bufinfo, MP_BUFFER_READ);
writeto(self, args[ARG_address].u_int, args[ARG_buffer].u_obj, args[ARG_start].u_int,
args[ARG_end].u_int, args[ARG_stop].u_bool);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_writeto);

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

// do the transfer
uint8_t status = shared_module_bitbangio_i2c_write(self, args[ARG_address].u_int,
((uint8_t*) bufinfo.buf) + start, length, args[ARG_stop].u_bool);
if (status != 0) {
mp_raise_OSError(status);
}
//| .. method:: writeto_then_readfrom(address, out_buffer, in_buffer, *, out_start=0, out_end=None, in_start=0, in_end=None)
//|
//| Write the bytes from ``out_buffer`` to the slave specified by ``address``, generate no stop
//| bit, generate a repeated start and read into ``in_buffer``. ``out_buffer`` and
//| ``in_buffer`` can be the same buffer because they are used sequentially.
//|
//| If ``start`` or ``end`` is provided, then the corresponding buffer will be sliced
//| as if ``buffer[start:end]``. This will not cause an allocation like ``buf[start:end]``
//| will so it saves memory.
//|
//| :param int address: 7-bit device address
//| :param bytearray out_buffer: buffer containing the bytes to write
//| :param bytearray in_buffer: buffer to write into
//| :param int out_start: Index to start writing from
//| :param int out_end: Index to read up to but not include. Defaults to ``len(buffer)``
//| :param int in_start: Index to start writing at
//| :param int in_end: Index to write up to but not include. Defaults to ``len(buffer)``
//|
STATIC mp_obj_t bitbangio_i2c_writeto_then_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_address, ARG_out_buffer, ARG_in_buffer, ARG_out_start, ARG_out_end, ARG_in_start, ARG_in_end };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_out_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_in_buffer, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_out_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_out_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
{ MP_QSTR_in_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_in_end, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = INT_MAX} },
};
bitbangio_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
check_for_deinit(self);
check_lock(self);
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);

writeto(self, args[ARG_address].u_int, args[ARG_out_buffer].u_obj, args[ARG_out_start].u_int,
args[ARG_out_end].u_int, false);
readfrom(self, args[ARG_address].u_int, args[ARG_in_buffer].u_obj, args[ARG_in_start].u_int,
args[ARG_in_end].u_int);

return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_obj, 1, bitbangio_i2c_writeto);
MP_DEFINE_CONST_FUN_OBJ_KW(bitbangio_i2c_writeto_then_readfrom_obj, 3, bitbangio_i2c_writeto_then_readfrom);

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

{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&bitbangio_i2c_writeto_obj) },
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&bitbangio_i2c_readfrom_into_obj) },
{ MP_ROM_QSTR(MP_QSTR_writeto_then_readfrom), MP_ROM_PTR(&bitbangio_i2c_writeto_then_readfrom_obj) },
};

STATIC MP_DEFINE_CONST_DICT(bitbangio_i2c_locals_dict, bitbangio_i2c_locals_dict_table);
Expand Down
4 changes: 2 additions & 2 deletions shared-bindings/bitbangio/SPI.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,13 +275,13 @@ STATIC mp_obj_t bitbangio_spi_write_readinto(size_t n_args, const mp_obj_t *pos_
mp_buffer_info_t buf_out_info;
mp_get_buffer_raise(args[ARG_buffer_out].u_obj, &buf_out_info, MP_BUFFER_READ);
int32_t out_start = args[ARG_out_start].u_int;
uint32_t out_length = buf_out_info.len;
size_t out_length = buf_out_info.len;
normalize_buffer_bounds(&out_start, args[ARG_out_end].u_int, &out_length);

mp_buffer_info_t buf_in_info;
mp_get_buffer_raise(args[ARG_buffer_in].u_obj, &buf_in_info, MP_BUFFER_WRITE);
int32_t in_start = args[ARG_in_start].u_int;
uint32_t in_length = buf_in_info.len;
size_t in_length = buf_in_info.len;
normalize_buffer_bounds(&in_start, args[ARG_in_end].u_int, &in_length);

if (out_length != in_length) {
Expand Down
Loading