aboutsummaryrefslogtreecommitdiff
path: root/extmod/machine_i2c.c
diff options
context:
space:
mode:
authorRadomir Dopieralski <openstack@sheep.art.pl>2016-09-19 20:53:08 +0200
committerDamien George <damien.p.george@gmail.com>2016-09-28 14:45:29 +1000
commit219245e10fa01ab81a7dd10b64fffd07e2ec1a49 (patch)
tree69523f0ef2e75184e0c0f141c8e059dad3c3817b /extmod/machine_i2c.c
parent7165fbd8f4e5b772d8fae6b2af9a8aad7524e81d (diff)
extmod/machine_i2c: Add support for the addrsize parameter in mem xfers.
The memory read/write I2C functions now take an optional keyword-only parameter that specifies the number of bits in the memory address. Only mem-addrs that are a multiple of 8-bits are supported (otherwise the behaviour is undefined). Due to the integer type used for the address, for values larger than 32 bits, only 32 bits of address will be sent, and the rest will be padded with 0s. Right now no exception is raised when that happens. For values smaller than 8, no address is sent. Also no exception then. Tested with a VL6180 sensor, which has 16-bit register addresses. Due to code refactoring, this patch reduces stmhal and esp8266 builds by about 50 bytes.
Diffstat (limited to 'extmod/machine_i2c.c')
-rw-r--r--extmod/machine_i2c.c134
1 files changed, 62 insertions, 72 deletions
diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c
index f7d238024..d76e5eedd 100644
--- a/extmod/machine_i2c.c
+++ b/extmod/machine_i2c.c
@@ -128,24 +128,6 @@ STATIC int mp_hal_i2c_write_byte(machine_i2c_obj_t *self, uint8_t val) {
return !ret;
}
-STATIC void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len) {
- mp_hal_i2c_start(self);
- if (!mp_hal_i2c_write_byte(self, addr << 1)) {
- goto er;
- }
- while (len--) {
- if (!mp_hal_i2c_write_byte(self, *data++)) {
- goto er;
- }
- }
- mp_hal_i2c_stop(self);
- return;
-
-er:
- mp_hal_i2c_stop(self);
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
-}
-
STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack) {
mp_hal_i2c_delay(self);
mp_hal_i2c_scl_low(self);
@@ -172,33 +154,27 @@ STATIC int mp_hal_i2c_read_byte(machine_i2c_obj_t *self, uint8_t *val, int nack)
return 1; // success
}
-STATIC void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len) {
- mp_hal_i2c_start(self);
- if (!mp_hal_i2c_write_byte(self, (addr << 1) | 1)) {
- goto er;
+// addr is the device address, memaddr is a memory address sent big-endian
+STATIC int mp_hal_i2c_write_addresses(machine_i2c_obj_t *self, uint8_t addr,
+ uint32_t memaddr, uint8_t addrsize) {
+ if (!mp_hal_i2c_write_byte(self, addr << 1)) {
+ return 0; // error
}
- while (len--) {
- if (!mp_hal_i2c_read_byte(self, data++, len == 0)) {
- goto er;
+ for (int16_t i = addrsize - 8; i >= 0; i -= 8) {
+ if (!mp_hal_i2c_write_byte(self, memaddr >> i)) {
+ return 0; // error
}
}
- mp_hal_i2c_stop(self);
- return;
-
-er:
- mp_hal_i2c_stop(self);
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
+ return 1; // success
}
-STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr, const uint8_t *src, size_t len) {
+STATIC void mp_hal_i2c_write_mem(machine_i2c_obj_t *self, uint8_t addr,
+ uint32_t memaddr, uint8_t addrsize, const uint8_t *src, size_t len) {
// start the I2C transaction
mp_hal_i2c_start(self);
// write the slave address and the memory address within the slave
- if (!mp_hal_i2c_write_byte(self, addr << 1)) {
- goto er;
- }
- if (!mp_hal_i2c_write_byte(self, memaddr)) {
+ if (!mp_hal_i2c_write_addresses(self, addr, memaddr, addrsize)) {
goto er;
}
@@ -218,20 +194,30 @@ er:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
}
-STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr, uint16_t memaddr, uint8_t *dest, size_t len) {
+STATIC void mp_hal_i2c_read_mem(machine_i2c_obj_t *self, uint8_t addr,
+ uint32_t memaddr, uint8_t addrsize, uint8_t *dest, size_t len) {
// start the I2C transaction
mp_hal_i2c_start(self);
- // write the slave address and the memory address within the slave
- if (!mp_hal_i2c_write_byte(self, addr << 1)) {
- goto er;
+ if (addrsize) {
+ // write the slave address and the memory address within the slave
+ if (!mp_hal_i2c_write_addresses(self, addr, memaddr, addrsize)) {
+ goto er;
+ }
+
+ // i2c_read will do a repeated start, and then read the I2C memory
+ mp_hal_i2c_start(self);
}
- if (!mp_hal_i2c_write_byte(self, memaddr)) {
+
+ if (!mp_hal_i2c_write_byte(self, (addr << 1) | 1)) {
goto er;
}
-
- // i2c_read will do a repeated start, and then read the I2C memory
- mp_hal_i2c_read(self, addr, dest, len);
+ while (len--) {
+ if (!mp_hal_i2c_read_byte(self, dest++, len == 0)) {
+ goto er;
+ }
+ }
+ mp_hal_i2c_stop(self);
return;
er:
@@ -239,6 +225,14 @@ er:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
}
+STATIC void mp_hal_i2c_write(machine_i2c_obj_t *self, uint8_t addr, const uint8_t *src, size_t len) {
+ mp_hal_i2c_write_mem(self, addr, 0, 0, src, len);
+}
+
+STATIC void mp_hal_i2c_read(machine_i2c_obj_t *self, uint8_t addr, uint8_t *dest, size_t len) {
+ mp_hal_i2c_read_mem(self, addr, 0, 0, dest, len);
+}
+
/******************************************************************************/
// MicroPython bindings for I2C
@@ -367,68 +361,64 @@ STATIC mp_obj_t machine_i2c_writeto(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_writeto_obj, machine_i2c_writeto);
+STATIC const mp_arg_t machine_i2c_mem_allowed_args[] = {
+ { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_arg, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} },
+};
+
STATIC mp_obj_t machine_i2c_readfrom_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_memaddr, ARG_n, ARG_addrsize };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
- //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
- };
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- 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);
+ mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
+ MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
// create the buffer to store data into
vstr_t vstr;
- vstr_init_len(&vstr, args[ARG_n].u_int);
+ vstr_init_len(&vstr, mp_obj_get_int(args[ARG_n].u_obj));
// do the transfer
- mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, (uint8_t*)vstr.buf, vstr.len);
+ mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int,
+ args[ARG_addrsize].u_int, (uint8_t*)vstr.buf, vstr.len);
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_obj, 1, machine_i2c_readfrom_mem);
+
STATIC mp_obj_t machine_i2c_readfrom_mem_into(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
- };
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- 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);
+ mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
+ MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
// get the buffer to store data into
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_WRITE);
// do the transfer
- mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len);
+ mp_hal_i2c_read_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int,
+ args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_readfrom_mem_into_obj, 1, machine_i2c_readfrom_mem_into);
STATIC mp_obj_t machine_i2c_writeto_mem(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_memaddr, ARG_buf, ARG_addrsize };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_memaddr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
- //{ MP_QSTR_addrsize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 8} }, TODO
- };
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
- 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);
+ mp_arg_val_t args[MP_ARRAY_SIZE(machine_i2c_mem_allowed_args)];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
+ MP_ARRAY_SIZE(machine_i2c_mem_allowed_args), machine_i2c_mem_allowed_args, args);
// get the buffer to write the data from
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[ARG_buf].u_obj, &bufinfo, MP_BUFFER_READ);
// do the transfer
- mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int, bufinfo.buf, bufinfo.len);
+ mp_hal_i2c_write_mem(self, args[ARG_addr].u_int, args[ARG_memaddr].u_int,
+ args[ARG_addrsize].u_int, bufinfo.buf, bufinfo.len);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_i2c_writeto_mem_obj, 1, machine_i2c_writeto_mem);