diff options
author | Damien George <damien.p.george@gmail.com> | 2016-03-14 11:56:23 +0000 |
---|---|---|
committer | Paul Sokolovsky <pfalcon@users.sourceforge.net> | 2016-03-24 11:46:05 +0200 |
commit | 0cdbd356fdd9dc5ad9c88bb0ee9b027b98981386 (patch) | |
tree | 126ec97c6c4b228e54873a954e2089f247baa0aa /esp8266/modpybi2c.c | |
parent | 5b9f361824a6a0dadcbbea1e66e59007d09c78fb (diff) | |
download | micropython-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.c | 67 |
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) }, }; |