|
28 | 28 | #include <stdint.h> |
29 | 29 | #include <string.h> |
30 | 30 |
|
| 31 | +#include "py/mperrno.h" |
31 | 32 | #include "py/mphal.h" |
32 | 33 | #include "py/runtime.h" |
33 | 34 | #include "extmod/machine_i2c.h" |
@@ -309,84 +310,101 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { |
309 | 310 | MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_scan_obj, machine_i2c_scan); |
310 | 311 |
|
311 | 312 | 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); |
315 | 321 | } |
316 | 322 | return mp_const_none; |
317 | 323 | } |
318 | 324 | MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_start_obj, machine_i2c_start); |
319 | 325 |
|
320 | 326 | 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); |
324 | 335 | } |
325 | 336 | return mp_const_none; |
326 | 337 | } |
327 | 338 | MP_DEFINE_CONST_FUN_OBJ_1(machine_i2c_stop_obj, machine_i2c_stop); |
328 | 339 |
|
329 | 340 | 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 | + } |
331 | 346 |
|
332 | 347 | // get the buffer to read into |
333 | 348 | mp_buffer_info_t bufinfo; |
334 | 349 | mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); |
335 | 350 |
|
336 | 351 | // 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); |
342 | 355 | } |
343 | 356 |
|
344 | 357 | return mp_const_none; |
345 | 358 | } |
346 | 359 | MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_readinto_obj, machine_i2c_readinto); |
347 | 360 |
|
348 | 361 | 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 | + } |
350 | 367 |
|
351 | 368 | // get the buffer to write from |
352 | 369 | mp_buffer_info_t bufinfo; |
353 | 370 | mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ); |
354 | 371 |
|
355 | 372 | // 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); |
361 | 376 | } |
362 | 377 |
|
363 | 378 | return mp_const_none; |
364 | 379 | } |
365 | 380 | MP_DEFINE_CONST_FUN_OBJ_2(machine_i2c_write_obj, machine_i2c_write); |
366 | 381 |
|
367 | 382 | 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; |
369 | 385 | vstr_t vstr; |
370 | 386 | 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); |
372 | 388 | return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); |
373 | 389 | } |
374 | 390 | MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_obj, machine_i2c_readfrom); |
375 | 391 |
|
376 | 392 | 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; |
378 | 395 | mp_buffer_info_t bufinfo; |
379 | 396 | 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); |
381 | 398 | return mp_const_none; |
382 | 399 | } |
383 | 400 | MP_DEFINE_CONST_FUN_OBJ_3(machine_i2c_readfrom_into_obj, machine_i2c_readfrom_into); |
384 | 401 |
|
385 | 402 | 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; |
387 | 405 | mp_buffer_info_t bufinfo; |
388 | 406 | 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); |
390 | 408 | return mp_const_none; |
391 | 409 | } |
392 | 410 | 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[] = { |
476 | 494 |
|
477 | 495 | STATIC MP_DEFINE_CONST_DICT(machine_i2c_locals_dict, machine_i2c_locals_dict_table); |
478 | 496 |
|
| 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 | + |
479 | 554 | const mp_obj_type_t machine_i2c_type = { |
480 | 555 | { &mp_type_type }, |
481 | 556 | .name = MP_QSTR_I2C, |
482 | 557 | .make_new = machine_i2c_make_new, |
| 558 | + .protocol = &mp_machine_soft_i2c_p, |
483 | 559 | .locals_dict = (mp_obj_dict_t*)&machine_i2c_locals_dict, |
484 | 560 | }; |
485 | 561 |
|
|
0 commit comments