esp8266: Implement bit-bang I2C read, and add i2c.readfrom method.

I2C reading tested with TSL2561 luminosity sensor.
This commit is contained in:
Damien George 2016-03-14 11:56:23 +00:00 committed by Paul Sokolovsky
parent 5b9f361824
commit 0cdbd356fd
2 changed files with 69 additions and 0 deletions

View File

@ -186,6 +186,52 @@ er:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error")); 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 // 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); 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) { 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 }; enum { ARG_addr, ARG_buf, ARG_stop };
static const mp_arg_t allowed_args[] = { 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[] = { 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_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) }, { MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&pyb_i2c_writeto_obj) },
}; };

View File

@ -148,10 +148,12 @@ Q(init)
Q(scl) Q(scl)
Q(sda) Q(sda)
Q(freq) Q(freq)
Q(readfrom)
Q(writeto) Q(writeto)
Q(stop) Q(stop)
Q(buf) Q(buf)
Q(addr) Q(addr)
Q(n)
// utime // utime
Q(utime) Q(utime)