Skip to content

Commit b983cfa

Browse files
committed
extmod/machine_i2c: Add a C-level I2C-protocol, refactoring soft I2C.
1 parent 63a5df3 commit b983cfa

2 files changed

Lines changed: 111 additions & 24 deletions

File tree

extmod/machine_i2c.c

Lines changed: 100 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <stdint.h>
2929
#include <string.h>
3030

31+
#include "py/mperrno.h"
3132
#include "py/mphal.h"
3233
#include "py/runtime.h"
3334
#include "extmod/machine_i2c.h"
@@ -309,84 +310,101 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) {
309310
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan);
310311

311312
STATIC mp_obj_t machine_i2c_start(mp_obj_t self_in) {
312-
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
313-
if (!mp_hal_i2c_start(self)) {
314-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
313+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
314+
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
315+
if (i2c_p->start == NULL) {
316+
mp_raise_msg(&mp_type_OSError, "I2C operation not supported");
317+
}
318+
int ret = i2c_p->start(self);
319+
if (ret != 0) {
320+
mp_raise_OSError(ret);
315321
}
316322
return mp_const_none;
317323
}
318324
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start);
319325

320326
STATIC mp_obj_t machine_i2c_stop(mp_obj_t self_in) {
321-
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
322-
if (!mp_hal_i2c_stop(self)) {
323-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
327+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
328+
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
329+
if (i2c_p->stop == NULL) {
330+
mp_raise_msg(&mp_type_OSError, "I2C operation not supported");
331+
}
332+
int ret = i2c_p->stop(self);
333+
if (ret != 0) {
334+
mp_raise_OSError(ret);
324335
}
325336
return mp_const_none;
326337
}
327338
MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop);
328339

329340
STATIC mp_obj_t machine_i2c_readinto(mp_obj_t self_in, mp_obj_t buf_in) {
330-
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
341+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
342+
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
343+
if (i2c_p->read == NULL) {
344+
mp_raise_msg(&mp_type_OSError, "I2C operation not supported");
345+
}
331346

332347
// get the buffer to read into
333348
mp_buffer_info_t bufinfo;
334349
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
335350

336351
// do the read
337-
uint8_t *dest = bufinfo.buf;
338-
while (bufinfo.len--) {
339-
if (!mp_hal_i2c_read_byte(self, dest++, bufinfo.len == 0)) {
340-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
341-
}
352+
int ret = i2c_p->read(self, bufinfo.buf, bufinfo.len);
353+
if (ret != 0) {
354+
mp_raise_OSError(ret);
342355
}
343356

344357
return mp_const_none;
345358
}
346359
MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_readinto_obj, machine_i2c_readinto);
347360

348361
STATIC mp_obj_t machine_i2c_write(mp_obj_t self_in, mp_obj_t buf_in) {
349-
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
362+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
363+
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
364+
if (i2c_p->write == NULL) {
365+
mp_raise_msg(&mp_type_OSError, "I2C operation not supported");
366+
}
350367

351368
// get the buffer to write from
352369
mp_buffer_info_t bufinfo;
353370
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
354371

355372
// do the write
356-
uint8_t *src = bufinfo.buf;
357-
while (bufinfo.len--) {
358-
if (!mp_hal_i2c_write_byte(self, *src++)) {
359-
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "I2C bus error"));
360-
}
373+
int ret = i2c_p->write(self, bufinfo.buf, bufinfo.len);
374+
if (ret != 0) {
375+
mp_raise_OSError(ret);
361376
}
362377

363378
return mp_const_none;
364379
}
365380
MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write);
366381

367382
STATIC mp_obj_t machine_i2c_readfrom(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t nbytes_in) {
368-
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
383+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
384+
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
369385
vstr_t vstr;
370386
vstr_init_len(&vstr, mp_obj_get_int(nbytes_in));
371-
mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)vstr.buf, vstr.len);
387+
i2c_p->readfrom(self, mp_obj_get_int(addr_in), (uint8_t*)vstr.buf, vstr.len, true);
372388
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
373389
}
374390
MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_obj, machine_i2c_readfrom);
375391

376392
STATIC mp_obj_t machine_i2c_readfrom_into(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) {
377-
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
393+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
394+
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
378395
mp_buffer_info_t bufinfo;
379396
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE);
380-
mp_hal_i2c_read(self, mp_obj_get_int(addr_in), (uint8_t*)bufinfo.buf, bufinfo.len);
397+
i2c_p->readfrom(self, mp_obj_get_int(addr_in), bufinfo.buf, bufinfo.len, true);
381398
return mp_const_none;
382399
}
383400
MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_into_obj, machine_i2c_readfrom_into);
384401

385402
STATIC mp_obj_t machine_i2c_writeto(mp_obj_t self_in, mp_obj_t addr_in, mp_obj_t buf_in) {
386-
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
403+
mp_obj_base_t *self = (mp_obj_base_t*)MP_OBJ_TO_PTR(self_in);
404+
mp_machine_i2c_p_t *i2c_p = (mp_machine_i2c_p_t*)self->type->protocol;
387405
mp_buffer_info_t bufinfo;
388406
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
389-
mp_hal_i2c_write(self, mp_obj_get_int(addr_in), bufinfo.buf, bufinfo.len);
407+
i2c_p->writeto(self, mp_obj_get_int(addr_in), bufinfo.buf, bufinfo.len, true);
390408
return mp_const_none;
391409
}
392410
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_writeto_obj, machine_i2c_writeto);
@@ -476,10 +494,68 @@ STATIC const mp_rom_map_elem_t machine_i2c_locals_dict_table[] = {
476494

477495
STATIC MP_DEFINE_CONST_DICT(machine_i2c_locals_dict, machine_i2c_locals_dict_table);
478496

497+
int mp_machine_soft_i2c_start(mp_obj_base_t *self_in) {
498+
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
499+
if (!mp_hal_i2c_start(self)) {
500+
return MP_ETIMEDOUT;
501+
}
502+
return 0; // success
503+
}
504+
505+
int mp_machine_soft_i2c_stop(mp_obj_base_t *self_in) {
506+
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
507+
if (!mp_hal_i2c_stop(self)) {
508+
return MP_ETIMEDOUT;
509+
}
510+
return 0; // success
511+
}
512+
513+
int mp_machine_soft_i2c_read(mp_obj_base_t *self_in, uint8_t *dest, size_t len) {
514+
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
515+
while (len--) {
516+
if (!mp_hal_i2c_read_byte(self, dest++, len == 0)) {
517+
return MP_ETIMEDOUT;
518+
}
519+
}
520+
return 0; // success
521+
}
522+
523+
int mp_machine_soft_i2c_write(mp_obj_base_t *self_in, const uint8_t *src, size_t len) {
524+
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
525+
while (len--) {
526+
if (!mp_hal_i2c_write_byte(self, *src++)) {
527+
return MP_ETIMEDOUT;
528+
}
529+
}
530+
return 0; // success
531+
}
532+
533+
int mp_machine_soft_i2c_readfrom(mp_obj_base_t *self_in, uint16_t addr, uint8_t *dest, size_t len, bool stop) {
534+
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
535+
mp_hal_i2c_read(self, addr, dest, len);
536+
return 0; // success
537+
}
538+
539+
int mp_machine_soft_i2c_writeto(mp_obj_base_t *self_in, uint16_t addr, const uint8_t *src, size_t len, bool stop) {
540+
machine_i2c_obj_t *self = (machine_i2c_obj_t*)self_in;
541+
mp_hal_i2c_write(self, addr, src, len);
542+
return 0; // success
543+
}
544+
545+
STATIC const mp_machine_i2c_p_t mp_machine_soft_i2c_p = {
546+
.start = mp_machine_soft_i2c_start,
547+
.stop = mp_machine_soft_i2c_stop,
548+
.read = mp_machine_soft_i2c_read,
549+
.write = mp_machine_soft_i2c_write,
550+
.readfrom = mp_machine_soft_i2c_readfrom,
551+
.writeto = mp_machine_soft_i2c_writeto,
552+
};
553+
479554
const mp_obj_type_t machine_i2c_type = {
480555
{ &mp_type_type },
481556
.name = MP_QSTR_I2C,
482557
.make_new = machine_i2c_make_new,
558+
.protocol = &mp_machine_soft_i2c_p,
483559
.locals_dict = (mp_obj_dict_t*)&machine_i2c_locals_dict,
484560
};
485561

extmod/machine_i2c.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@
2929

3030
#include "py/obj.h"
3131

32+
// I2C protocol
33+
// the first 4 methods can be NULL, meaning operation is not supported
34+
typedef struct _mp_machine_i2c_p_t {
35+
int (*start)(mp_obj_base_t *obj);
36+
int (*stop)(mp_obj_base_t *obj);
37+
int (*read)(mp_obj_base_t *obj, uint8_t *dest, size_t len);
38+
int (*write)(mp_obj_base_t *obj, const uint8_t *src, size_t len);
39+
int (*readfrom)(mp_obj_base_t *obj, uint16_t addr, uint8_t *dest, size_t len, bool stop);
40+
int (*writeto)(mp_obj_base_t *obj, uint16_t addr, const uint8_t *src, size_t len, bool stop);
41+
} mp_machine_i2c_p_t;
42+
3243
extern const mp_obj_type_t machine_i2c_type;
3344

3445
#endif // __MICROPY_INCLUDED_EXTMOD_MACHINE_I2C_H__

0 commit comments

Comments
 (0)