Skip to content

Commit 0cdbd35

Browse files
dpgeorgepfalcon
authored andcommitted
esp8266: Implement bit-bang I2C read, and add i2c.readfrom method.
I2C reading tested with TSL2561 luminosity sensor.
1 parent 5b9f361 commit 0cdbd35

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

esp8266/modpybi2c.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,52 @@ STATIC void mphal_i2c_write(pyb_i2c_obj_t *self, uint8_t addr, uint8_t *data, si
186186
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
187187
}
188188

189+
STATIC int mphal_i2c_read_byte(pyb_i2c_obj_t *self, uint8_t *val) {
190+
mphal_i2c_wait_a();
191+
mphal_i2c_set_scl(self, 0);
192+
mphal_i2c_wait_a();
193+
194+
uint8_t dat = 0;
195+
for (int i = 7; i >= 0; i--) {
196+
mphal_i2c_set_scl(self, 1);
197+
mphal_i2c_wait_a();
198+
dat = (dat << 1) | mphal_i2c_get_sda(self);
199+
mphal_i2c_wait_a();
200+
mphal_i2c_set_scl(self, 0);
201+
mphal_i2c_wait_a();
202+
}
203+
*val = dat;
204+
205+
mphal_i2c_wait_a();
206+
mphal_i2c_set_scl(self, 1);
207+
mphal_i2c_wait_a();
208+
mphal_i2c_wait_b();
209+
mphal_i2c_set_scl(self, 0);
210+
mphal_i2c_wait_a();
211+
212+
return 1; // success
213+
}
214+
215+
STATIC void mphal_i2c_read(pyb_i2c_obj_t *self, uint8_t addr, uint8_t *data, size_t len, bool stop) {
216+
mphal_i2c_start(self);
217+
if (!mphal_i2c_write_byte(self, (addr << 1) | 1)) {
218+
goto er;
219+
}
220+
while (len--) {
221+
if (!mphal_i2c_read_byte(self, data++)) {
222+
goto er;
223+
}
224+
}
225+
if (stop) {
226+
mphal_i2c_stop(self);
227+
}
228+
return;
229+
230+
er:
231+
mphal_i2c_stop(self);
232+
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
233+
}
234+
189235
/******************************************************************************/
190236
// MicroPython bindings for I2C
191237

@@ -219,6 +265,26 @@ STATIC mp_obj_t pyb_i2c_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_
219265
}
220266
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_obj_init);
221267

268+
STATIC mp_obj_t pyb_i2c_readfrom(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
269+
enum { ARG_addr, ARG_n, ARG_stop };
270+
static const mp_arg_t allowed_args[] = {
271+
{ MP_QSTR_addr, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
272+
{ MP_QSTR_n, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = 0} },
273+
{ MP_QSTR_stop, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} },
274+
};
275+
pyb_i2c_obj_t *self = pos_args[0];
276+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
277+
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
278+
279+
// do the I2C transfer
280+
vstr_t vstr;
281+
vstr_init_len(&vstr, args[ARG_n].u_int);
282+
mphal_i2c_read(self, args[ARG_addr].u_int, (uint8_t*)vstr.buf, vstr.len, args[ARG_stop].u_bool);
283+
284+
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
285+
}
286+
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_obj, 1, pyb_i2c_readfrom);
287+
222288
STATIC mp_obj_t pyb_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
223289
enum { ARG_addr, ARG_buf, ARG_stop };
224290
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);
243309

244310
STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = {
245311
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_i2c_init_obj) },
312+
{ MP_ROM_QSTR(MP_QSTR_readfrom), MP_ROM_PTR(&pyb_i2c_readfrom_obj) },
246313
{ MP_ROM_QSTR(MP_QSTR_writeto), MP_ROM_PTR(&pyb_i2c_writeto_obj) },
247314
};
248315

esp8266/qstrdefsport.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,12 @@ Q(init)
148148
Q(scl)
149149
Q(sda)
150150
Q(freq)
151+
Q(readfrom)
151152
Q(writeto)
152153
Q(stop)
153154
Q(buf)
154155
Q(addr)
156+
Q(n)
155157

156158
// utime
157159
Q(utime)

0 commit comments

Comments
 (0)