extmod/machine_i2c: Add i2c.writevto() that can write a vector of bufs.

For example: i2c.writevto(addr, (buf1, buf2)).  This allows to efficiently
(wrt memory) write data composed of separate buffers, such as a command
followed by a large amount of data.
pull/1/head
Damien George 2019-05-08 18:33:54 +10:00
parent 8bcb552d97
commit b10d0664be
1 changed files with 47 additions and 0 deletions

View File

@ -480,6 +480,52 @@ STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto);
STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
mp_int_t addr = mp_obj_get_int(args[1]);
// Get the list of data buffer(s) to write
size_t nitems;
const mp_obj_t *items;
mp_obj_get_array(args[2], &nitems, (mp_obj_t**)&items);
// Get the stop argument
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
// Extract all buffer data, skipping zero-length buffers
size_t alloc = nitems == 0 ? 1 : nitems;
size_t nbufs = 0;
mp_machine_i2c_buf_t *bufs = mp_local_alloc(alloc * sizeof(mp_machine_i2c_buf_t));
for (; nitems--; ++items) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(*items, &bufinfo, MP_BUFFER_READ);
if (bufinfo.len > 0) {
bufs[nbufs].len = bufinfo.len;
bufs[nbufs++].buf = bufinfo.buf;
}
}
// Make sure there is at least one buffer, empty if needed
if (nbufs == 0) {
bufs[0].len = 0;
bufs[0].buf = NULL;
nbufs = 1;
}
// Do the I2C transfer
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0);
mp_local_free(bufs);
if (ret < 0) {
mp_raise_OSError(-ret);
}
// Return number of acks received
return MP_OBJ_NEW_SMALL_INT(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto);
STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
uint8_t memaddr_buf[4];
@ -601,6 +647,7 @@ STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
{ 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) },
{ MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) },
// memory operations
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },