Skip to content

Commit b10d066

Browse files
committed
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.
1 parent 8bcb552 commit b10d066

1 file changed

Lines changed: 47 additions & 0 deletions

File tree

extmod/machine_i2c.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,52 @@ STATIC mp_obj_t machine_i2c_writeto(size_t n_args, const mp_obj_t *args) {
480480
}
481481
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writeto_obj, 3, 4, machine_i2c_writeto);
482482

483+
STATIC mp_obj_t machine_i2c_writevto(size_t n_args, const mp_obj_t *args) {
484+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
485+
mp_int_t addr = mp_obj_get_int(args[1]);
486+
487+
// Get the list of data buffer(s) to write
488+
size_t nitems;
489+
const mp_obj_t *items;
490+
mp_obj_get_array(args[2], &nitems, (mp_obj_t**)&items);
491+
492+
// Get the stop argument
493+
bool stop = (n_args == 3) ? true : mp_obj_is_true(args[3]);
494+
495+
// Extract all buffer data, skipping zero-length buffers
496+
size_t alloc = nitems == 0 ? 1 : nitems;
497+
size_t nbufs = 0;
498+
mp_machine_i2c_buf_t *bufs = mp_local_alloc(alloc * sizeof(mp_machine_i2c_buf_t));
499+
for (; nitems--; ++items) {
500+
mp_buffer_info_t bufinfo;
501+
mp_get_buffer_raise(*items, &bufinfo, MP_BUFFER_READ);
502+
if (bufinfo.len > 0) {
503+
bufs[nbufs].len = bufinfo.len;
504+
bufs[nbufs++].buf = bufinfo.buf;
505+
}
506+
}
507+
508+
// Make sure there is at least one buffer, empty if needed
509+
if (nbufs == 0) {
510+
bufs[0].len = 0;
511+
bufs[0].buf = NULL;
512+
nbufs = 1;
513+
}
514+
515+
// Do the I2C transfer
516+
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
517+
int ret = i2c_p->transfer(self, addr, nbufs, bufs, stop ? MP_MACHINE_I2C_FLAG_STOP : 0);
518+
mp_local_free(bufs);
519+
520+
if (ret < 0) {
521+
mp_raise_OSError(-ret);
522+
}
523+
524+
// Return number of acks received
525+
return MP_OBJ_NEW_SMALL_INT(ret);
526+
}
527+
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_i2c_writevto_obj, 3, 4, machine_i2c_writevto);
528+
483529
STATIC int read_mem(mp_obj_t self_in, uint16_t addr, uint32_t memaddr, uint8_t addrsize, uint8_t *buf, size_t len) {
484530
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
485531
uint8_t memaddr_buf[4];
@@ -601,6 +647,7 @@ STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
601647
{ MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&machine_i2c_readfrom_obj) },
602648
{ MP_ROM_QSTR(MP_QSTR_readfrom_into), MP_ROM_PTR(&machine_i2c_readfrom_into_obj) },
603649
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&machine_i2c_writeto_obj) },
650+
{ MP_ROM_QSTR(MP_QSTR_writevto), MP_ROM_PTR(&machine_i2c_writevto_obj) },
604651

605652
// memory operations
606653
{ MP_ROM_QSTR(MP_QSTR_readfrom_mem), MP_ROM_PTR(&machine_i2c_readfrom_mem_obj) },

0 commit comments

Comments
 (0)