summaryrefslogtreecommitdiffstatshomepage
path: root/esp8266/modpybi2c.c
diff options
context:
space:
mode:
authorDamien George <damien.p.george@gmail.com>2016-03-14 11:56:23 +0000
committerPaul Sokolovsky <pfalcon@users.sourceforge.net>2016-03-24 11:46:05 +0200
commit0cdbd356fdd9dc5ad9c88bb0ee9b027b98981386 (patch)
tree126ec97c6c4b228e54873a954e2089f247baa0aa /esp8266/modpybi2c.c
parent5b9f361824a6a0dadcbbea1e66e59007d09c78fb (diff)
downloadmicropython-0cdbd356fdd9dc5ad9c88bb0ee9b027b98981386.tar.gz
micropython-0cdbd356fdd9dc5ad9c88bb0ee9b027b98981386.zip
esp8266: Implement bit-bang I2C read, and add i2c.readfrom method.
I2C reading tested with TSL2561 luminosity sensor.
Diffstat (limited to 'esp8266/modpybi2c.c')
-rw-r--r--esp8266/modpybi2c.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/esp8266/modpybi2c.c b/esp8266/modpybi2c.c
index ad65d431b5..0216abeb99 100644
--- a/esp8266/modpybi2c.c
+++ b/esp8266/modpybi2c.c
@@ -186,6 +186,52 @@ er:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
}
+STATIC int mphal_i2c_read_byte(pyb_i2c_obj_t *self, uint8_t *val) {
+ mphal_i2c_wait_a();
+ mphal_i2c_set_scl(self, 0);
+ mphal_i2c_wait_a();
+
+ uint8_t dat = 0;
+ for (int i = 7; i >= 0; i--) {
+ mphal_i2c_set_scl(self, 1);
+ mphal_i2c_wait_a();
+ dat = (dat << 1) | mphal_i2c_get_sda(self);
+ mphal_i2c_wait_a();
+ mphal_i2c_set_scl(self, 0);
+ mphal_i2c_wait_a();
+ }
+ *val = dat;
+
+ mphal_i2c_wait_a();
+ mphal_i2c_set_scl(self, 1);
+ mphal_i2c_wait_a();
+ mphal_i2c_wait_b();
+ mphal_i2c_set_scl(self, 0);
+ mphal_i2c_wait_a();
+
+ return 1; // success
+}
+
+STATIC void mphal_i2c_read(pyb_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len, bool stop) {
+ mphal_i2c_start(self);
+ if (!mphal_i2c_write_byte(self, (addr << 1) | 1)) {
+ goto er;
+ }
+ while (len--) {
+ if (!mphal_i2c_read_byte(self, data++)) {
+ goto er;
+ }
+ }
+ if (stop) {
+ mphal_i2c_stop(self);
+ }
+ return;
+
+er:
+ mphal_i2c_stop(self);
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
+}
+
/******************************************************************************/
// MicroPython bindings for I2C
@@ -219,6 +265,26 @@ STATIC mp_obj_t pyb_i2c_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_obj_init);
+STATIC mp_obj_t pyb_i2c_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_addr, ARG_n, ARG_stop };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
+ { MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
+ };
+ pyb_i2c_obj_t *self = 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);
+
+ // do the I2C transfer
+ vstr_t vstr;
+ vstr_init_len(&vstr, args[ARG_n].u_int);
+ mphal_i2c_read(self, args[ARG_addr].u_int, (uint8_t*)vstr.buf, vstr.len, args[ARG_stop].u_bool);
+
+ return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 1, pyb_i2c_readfrom);
+
STATIC mp_obj_t pyb_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_addr, ARG_buf, ARG_stop };
static const mp_arg_t allowed_args[] = {
@@ -243,6 +309,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_obj, 1, pyb_i2c_writeto);
STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_i2c_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&pyb_i2c_readfrom_obj) },
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&pyb_i2c_writeto_obj) },
};