From d1df04a8a51d1cb5def81e3360c7ecd1e5156c13 Mon Sep 17 00:00:00 2001 From: sys64738 Date: Mon, 21 Jun 2021 00:07:42 +0200 Subject: [PATCH] 10-bit i2c addr support, better address probes --- bsp/rp2040/i2c_tinyusb.c | 50 ++++++++++++++++++++++------------------ src/vnd_i2ctinyusb.c | 14 +++++------ 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/bsp/rp2040/i2c_tinyusb.c b/bsp/rp2040/i2c_tinyusb.c index 215532e..fec8096 100644 --- a/bsp/rp2040/i2c_tinyusb.c +++ b/bsp/rp2040/i2c_tinyusb.c @@ -69,7 +69,7 @@ static bool __no_inline_not_in_flash_func(i2cio_write7)(uint8_t v) { // return v i2cio_set_sda(true); i2cio_set_scl(true); - bool ack = i2cio_get_sda(); + bool ack = !i2cio_get_sda(); i2cio_set_scl(false); return ack; @@ -83,7 +83,7 @@ static bool __no_inline_not_in_flash_func(i2cio_write8)(uint8_t v) { // return v i2cio_set_sda(true); i2cio_set_scl(true); - bool ack = i2cio_get_sda(); + bool ack = !i2cio_get_sda(); i2cio_set_scl(false); return ack; @@ -141,7 +141,11 @@ static int __no_inline_not_in_flash_func(i2cex_probe_address)(uint16_t addr, boo return rv; } -static void i2cex_abort_xfer(i2c_inst_t* i2c) { +inline static void i2cex_abort_xfer(i2c_inst_t* i2c) { +#if 1 + // may be bugged??? so doesnt do anything for now + return; +#else // now do the abort i2c->hw->enable = 1 /*| (1<<2)*/ | (1<<1); // wait for M_TX_ABRT irq @@ -155,6 +159,7 @@ static void i2cex_abort_xfer(i2c_inst_t* i2c) { // reset irq //if (!timeout) (void)i2c->hw->clr_tx_abrt; +#endif } static int i2cex_write_blocking_until(i2c_inst_t* i2c, uint16_t addr, bool a10bit, @@ -315,22 +320,22 @@ static int i2cex_read_blocking_until(i2c_inst_t* i2c, uint16_t addr, bool a10bit if (abort) break; uint8_t v = (uint8_t)i2c->hw->data_cmd; - printf("\ngot read %02x\n", v); + //printf("\ngot read %02x\n", v); *dst++ = v; } int rval; if (abort) { - printf("\ngot abrt: "); + //printf("\ngot abrt: "); const int addr_noack = I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS | I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR1_NOACK_BITS | I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_BITS; - if (timeout) { printf("timeout\n"); rval = PICO_ERROR_TIMEOUT; } - else if (!abort_reason || (abort_reason & addr_noack)) {printf("disconn\n"); + if (timeout) { /*printf("timeout\n");*/ rval = PICO_ERROR_TIMEOUT; } + else if (!abort_reason || (abort_reason & addr_noack)) {//printf("disconn\n"); rval = PICO_ERROR_GENERIC; } - else {printf("unk\n"); rval = PICO_ERROR_GENERIC;} + else {/*printf("unk\n");*/ rval = PICO_ERROR_GENERIC;} } else rval = byte_ctr; i2c->restart_on_next = nostop; @@ -349,10 +354,9 @@ static inline int i2cex_read_timeout_us(i2c_inst_t* i2c, uint16_t addr, bool a10 __attribute__((__const__)) enum ki2c_funcs i2ctu_get_func(void) { - // TODO: 10bit addresses // TODO: SMBUS_EMUL_ALL => I2C_M_RECV_LEN // TODO: maybe also PROTOCOL_MANGLING, NOSTART - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; } void i2ctu_init(void) { @@ -376,22 +380,21 @@ uint32_t i2ctu_set_freq(uint32_t freq, uint32_t us) { return i2c_set_baudrate(PINOUT_I2C_DEV, freq); } -// TODO: FIX START AND STOP COND HANDLING. MAYBE. BUG IN vnd_i2ctinyusb.c MORE SERIOUS -// ALSO TODO: i2cex routines seem to mess with the I2C bus when a timeout (=> abort) happens? enum itu_status i2ctu_write(enum ki2c_flags flags, enum itu_command startstopflags, uint16_t addr, const uint8_t* buf, size_t len) { bool nostop = !(startstopflags & ITU_CMD_I2C_IO_END); - printf("nostop=%c ", nostop?'t':'f'); + //printf("nostop=%c ", nostop?'t':'f'); + bool bit10 = flags & I2C_M_TEN; - if (len == 0) { + /*if (len == 0) { // do a read, that's less hazardous uint8_t stuff = 0; - int rv = i2c_read_timeout_us(PINOUT_I2C_DEV, addr, /*false,*/ &stuff, 1, + int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, &stuff, 1, nostop, 1000*1000); if (rv < 0) return ITU_STATUS_ADDR_NAK; return ITU_STATUS_ADDR_ACK; - } else { - int rv = i2c_write_timeout_us(PINOUT_I2C_DEV, addr, /*false,*/ buf, len, + } else*/ { + int rv = i2cex_write_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len, nostop, 1000*1000); if (rv < 0 || (size_t)rv < len) return ITU_STATUS_ADDR_NAK; return ITU_STATUS_ADDR_ACK; @@ -400,18 +403,19 @@ enum itu_status i2ctu_write(enum ki2c_flags flags, enum itu_command startstopfla enum itu_status i2ctu_read(enum ki2c_flags flags, enum itu_command startstopflags, uint16_t addr, uint8_t* buf, size_t len) { bool nostop = !(startstopflags & ITU_CMD_I2C_IO_END); - printf("nostop=%c ", nostop?'t':'f'); + //printf("nostop=%c ", nostop?'t':'f'); + bool bit10 = flags & I2C_M_TEN; - if (len == 0) { + /*if (len == 0) { uint8_t stuff = 0; - int rv = i2c_read_timeout_us(PINOUT_I2C_DEV, addr, /*false,*/ &stuff, 1, + int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, &stuff, 1, nostop, 1000*1000); if (rv < 0) return ITU_STATUS_ADDR_NAK; return ITU_STATUS_ADDR_ACK; - } else { - int rv = i2c_read_timeout_us(PINOUT_I2C_DEV, addr, /*false,*/ buf, len, + } else*/ { + int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len, nostop, 1000*1000); - printf("p le rv=%d buf=%02x ", rv, buf[0]); + //printf("p le rv=%d buf=%02x ", rv, buf[0]); if (rv < 0 || (size_t)rv < len) return ITU_STATUS_ADDR_NAK; return ITU_STATUS_ADDR_ACK; } diff --git a/src/vnd_i2ctinyusb.c b/src/vnd_i2ctinyusb.c index 9c8e948..76a3392 100644 --- a/src/vnd_i2ctinyusb.c +++ b/src/vnd_i2ctinyusb.c @@ -69,9 +69,9 @@ static bool iub_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t co if (req->bRequest >= ITU_CMD_I2C_IO && req->bRequest <= ITU_CMD_I2C_IO_BEGINEND && cmd.cmd == req->bRequest && cmd.flags == req->wValue && cmd.addr == req->wIndex && cmd.len == req->wLength) { - printf("WDATA a=%04hx l=%04hx ", cmd.addr, cmd.len); + //printf("WDATA a=%04hx l=%04hx ", cmd.addr, cmd.len); - printf("data=%02x %02x...\n", rxbuf[0], rxbuf[1]); + //printf("data=%02x %02x...\n", rxbuf[0], rxbuf[1]); status = i2ctu_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK, cmd.addr, rxbuf, cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len); @@ -132,19 +132,19 @@ static bool iub_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t co cmd.cmd = req->bRequest; if (cmd.flags & I2C_M_RD) { // read from I2C device - printf("read addr=%04hx len=%04hx ", cmd.addr, cmd.len); + //printf("read addr=%04hx len=%04hx ", cmd.addr, cmd.len); status = i2ctu_read(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK, cmd.addr, txbuf, cmd.len); - printf("data=%02x %02x...\n", txbuf[0], txbuf[1]); + //printf("data=%02x %02x...\n", txbuf[0], txbuf[1]); return tud_control_xfer(rhport, req, txbuf, cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len); } else { // write - printf("write addr=%04hx len=%04hx ", cmd.addr, cmd.len); + //printf("write addr=%04hx len=%04hx ", cmd.addr, cmd.len); if (cmd.len == 0) { // address probe -> do this here uint8_t bleh = 0; status = i2ctu_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK, cmd.addr, &bleh, 0); - printf("probe -> %d\n", status); + //printf("probe -> %d\n", status); return tud_control_status(rhport, req); } else { // handled in DATA stage! @@ -157,7 +157,7 @@ static bool iub_ctl_req(uint8_t rhport, uint8_t stage, tusb_control_request_t co } break; default: - printf("I2C-Tiny-USB: unknown command %02x\n", req->bRequest); + //printf("I2C-Tiny-USB: unknown command %02x\n", req->bRequest); return false; } } else return true; // other stage...