MicroPython: Make Pimoroni I2C compatible with machine.I2C

This commit is contained in:
Phil Howard 2022-05-17 15:23:40 +01:00
parent 698dd4d2c7
commit 7d3b48c509
3 changed files with 59 additions and 4 deletions

View File

@ -5,15 +5,20 @@
////////////////////////////////////////////////////////////////////////////////////////////////////
/***** Methods *****/
/*
MP_DEFINE_CONST_FUN_OBJ_1(PimoroniI2C___del___obj, PimoroniI2C___del__);
/***** Binding of Methods *****/
STATIC const mp_rom_map_elem_t PimoroniI2C_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&PimoroniI2C___del___obj) },
};
STATIC MP_DEFINE_CONST_DICT(PimoroniI2C_locals_dict, PimoroniI2C_locals_dict_table);
*/
STATIC const mp_machine_i2c_p_t machine_i2c_p = {
.transfer = mp_machine_i2c_transfer_adaptor,
.transfer_single = machine_i2c_transfer_single,
};
/***** Class Definition *****/
const mp_obj_type_t PimoroniI2C_type = {
@ -21,7 +26,8 @@ const mp_obj_type_t PimoroniI2C_type = {
.name = MP_QSTR_pimoroni_i2c,
.print = PimoroniI2C_print,
.make_new = PimoroniI2C_make_new,
.locals_dict = (mp_obj_dict_t*)&PimoroniI2C_locals_dict,
.protocol = &machine_i2c_p,
.locals_dict = (mp_obj_dict_t*)&mp_machine_i2c_locals_dict,
};

View File

@ -12,6 +12,9 @@ using namespace pimoroni;
extern "C" {
#include "pimoroni_i2c.h"
#include "py/mperrno.h"
#include "extmod/machine_i2c.h"
#include "hardware/i2c.h"
/***** Variables Struct *****/
typedef struct _PimoroniI2C_obj_t {
@ -83,4 +86,47 @@ mp_obj_t PimoroniI2C_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
return MP_OBJ_FROM_PTR(self);
}
// Reimplementation of the RP2 port's machine_i2c_transfer_single in terms of Pimoroni I2C
// https://github.com/micropython/micropython/blob/1fb01bd6c5dc350f3c617ca8edae8dea9e5516ae/ports/rp2/machine_i2c.c#L123
int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags) {
_PimoroniI2C_obj_t *self = (_PimoroniI2C_obj_t *)self_in;
int ret;
bool nostop = !(flags & MP_MACHINE_I2C_FLAG_STOP);
if (flags & MP_MACHINE_I2C_FLAG_READ) {
ret = i2c_read_blocking(self->i2c->get_i2c(), addr, buf, len, nostop);
} else {
if (len == 0) {
// Workaround issue with hardware I2C not accepting zero-length writes.
mp_machine_soft_i2c_obj_t soft_i2c = {
.base = { &mp_machine_soft_i2c_type },
.us_delay = 500000 / self->i2c->get_baudrate() + 1,
.us_timeout = 50000,
.scl = self->i2c->get_scl(),
.sda = self->i2c->get_sda(),
};
mp_machine_i2c_buf_t bufs = {
.len = len,
.buf = buf,
};
mp_hal_pin_open_drain(self->i2c->get_scl());
mp_hal_pin_open_drain(self->i2c->get_sda());
ret = mp_machine_soft_i2c_transfer(&soft_i2c.base, addr, 1, &bufs, flags);
gpio_set_function(self->i2c->get_scl(), GPIO_FUNC_I2C);
gpio_set_function(self->i2c->get_sda(), GPIO_FUNC_I2C);
return ret;
} else {
ret = i2c_write_blocking(self->i2c->get_i2c(), addr, buf, len, nostop);
}
}
if (ret < 0) {
if (ret == PICO_ERROR_TIMEOUT) {
return -MP_ETIMEDOUT;
} else {
return -MP_EIO;
}
} else {
return ret;
}
}
}

View File

@ -1,5 +1,6 @@
// Include MicroPython API.
#include "py/runtime.h"
#include "extmod/machine_i2c.h"
/***** Extern of Class Definition *****/
extern const mp_obj_type_t PimoroniI2C_type;
@ -9,4 +10,6 @@ extern void PimoroniI2C_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
extern mp_obj_t PimoroniI2C_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
extern mp_obj_t PimoroniI2C___del__(mp_obj_t self_in);
extern bool Pimoroni_mp_obj_to_i2c(mp_obj_t in, void *out);
extern bool Pimoroni_mp_obj_to_i2c(mp_obj_t in, void *out);
extern int machine_i2c_transfer_single(mp_obj_base_t *self_in, uint16_t addr, size_t len, uint8_t *buf, unsigned int flags);