10-bit i2c addr support, better address probes

This commit is contained in:
Triss 2021-06-21 00:07:42 +02:00
parent df797cbeb4
commit d1df04a8a5
2 changed files with 34 additions and 30 deletions

View File

@ -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_sda(true);
i2cio_set_scl(true); i2cio_set_scl(true);
bool ack = i2cio_get_sda(); bool ack = !i2cio_get_sda();
i2cio_set_scl(false); i2cio_set_scl(false);
return ack; 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_sda(true);
i2cio_set_scl(true); i2cio_set_scl(true);
bool ack = i2cio_get_sda(); bool ack = !i2cio_get_sda();
i2cio_set_scl(false); i2cio_set_scl(false);
return ack; return ack;
@ -141,7 +141,11 @@ static int __no_inline_not_in_flash_func(i2cex_probe_address)(uint16_t addr, boo
return rv; 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 // now do the abort
i2c->hw->enable = 1 /*| (1<<2)*/ | (1<<1); i2c->hw->enable = 1 /*| (1<<2)*/ | (1<<1);
// wait for M_TX_ABRT irq // wait for M_TX_ABRT irq
@ -155,6 +159,7 @@ static void i2cex_abort_xfer(i2c_inst_t* i2c) {
// reset irq // reset irq
//if (!timeout) //if (!timeout)
(void)i2c->hw->clr_tx_abrt; (void)i2c->hw->clr_tx_abrt;
#endif
} }
static int i2cex_write_blocking_until(i2c_inst_t* i2c, uint16_t addr, bool a10bit, 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; if (abort) break;
uint8_t v = (uint8_t)i2c->hw->data_cmd; uint8_t v = (uint8_t)i2c->hw->data_cmd;
printf("\ngot read %02x\n", v); //printf("\ngot read %02x\n", v);
*dst++ = v; *dst++ = v;
} }
int rval; int rval;
if (abort) { if (abort) {
printf("\ngot abrt: "); //printf("\ngot abrt: ");
const int addr_noack = I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS 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_10ADDR1_NOACK_BITS
| I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_BITS; | I2C_IC_TX_ABRT_SOURCE_ABRT_10ADDR2_NOACK_BITS;
if (timeout) { printf("timeout\n"); rval = PICO_ERROR_TIMEOUT; } if (timeout) { /*printf("timeout\n");*/ rval = PICO_ERROR_TIMEOUT; }
else if (!abort_reason || (abort_reason & addr_noack)) {printf("disconn\n"); else if (!abort_reason || (abort_reason & addr_noack)) {//printf("disconn\n");
rval = PICO_ERROR_GENERIC; } rval = PICO_ERROR_GENERIC; }
else {printf("unk\n"); rval = PICO_ERROR_GENERIC;} else {/*printf("unk\n");*/ rval = PICO_ERROR_GENERIC;}
} else rval = byte_ctr; } else rval = byte_ctr;
i2c->restart_on_next = nostop; 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__)) __attribute__((__const__))
enum ki2c_funcs i2ctu_get_func(void) { enum ki2c_funcs i2ctu_get_func(void) {
// TODO: 10bit addresses
// TODO: SMBUS_EMUL_ALL => I2C_M_RECV_LEN // TODO: SMBUS_EMUL_ALL => I2C_M_RECV_LEN
// TODO: maybe also PROTOCOL_MANGLING, NOSTART // 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) { 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); 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, enum itu_status i2ctu_write(enum ki2c_flags flags, enum itu_command startstopflags,
uint16_t addr, const uint8_t* buf, size_t len) { uint16_t addr, const uint8_t* buf, size_t len) {
bool nostop = !(startstopflags & ITU_CMD_I2C_IO_END); 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 // do a read, that's less hazardous
uint8_t stuff = 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); nostop, 1000*1000);
if (rv < 0) return ITU_STATUS_ADDR_NAK; if (rv < 0) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK; return ITU_STATUS_ADDR_ACK;
} else { } else*/ {
int rv = i2c_write_timeout_us(PINOUT_I2C_DEV, addr, /*false,*/ buf, len, int rv = i2cex_write_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len,
nostop, 1000*1000); nostop, 1000*1000);
if (rv < 0 || (size_t)rv < len) return ITU_STATUS_ADDR_NAK; if (rv < 0 || (size_t)rv < len) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK; 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, enum itu_status i2ctu_read(enum ki2c_flags flags, enum itu_command startstopflags,
uint16_t addr, uint8_t* buf, size_t len) { uint16_t addr, uint8_t* buf, size_t len) {
bool nostop = !(startstopflags & ITU_CMD_I2C_IO_END); 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; 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); nostop, 1000*1000);
if (rv < 0) return ITU_STATUS_ADDR_NAK; if (rv < 0) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK; return ITU_STATUS_ADDR_ACK;
} else { } else*/ {
int rv = i2c_read_timeout_us(PINOUT_I2C_DEV, addr, /*false,*/ buf, len, int rv = i2cex_read_timeout_us(PINOUT_I2C_DEV, addr, bit10, buf, len,
nostop, 1000*1000); 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; if (rv < 0 || (size_t)rv < len) return ITU_STATUS_ADDR_NAK;
return ITU_STATUS_ADDR_ACK; return ITU_STATUS_ADDR_ACK;
} }

View File

@ -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 if (req->bRequest >= ITU_CMD_I2C_IO && req->bRequest <= ITU_CMD_I2C_IO_BEGINEND
&& cmd.cmd == req->bRequest && cmd.flags == req->wValue && cmd.cmd == req->bRequest && cmd.flags == req->wValue
&& cmd.addr == req->wIndex && cmd.len == req->wLength) { && 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, status = i2ctu_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK,
cmd.addr, rxbuf, cmd.len > sizeof rxbuf ? sizeof rxbuf : cmd.len); 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; cmd.cmd = req->bRequest;
if (cmd.flags & I2C_M_RD) { // read from I2C device 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, status = i2ctu_read(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK,
cmd.addr, txbuf, cmd.len); 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, return tud_control_xfer(rhport, req, txbuf,
cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len); cmd.len > sizeof txbuf ? sizeof txbuf : cmd.len);
} else { // write } 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 if (cmd.len == 0) { // address probe -> do this here
uint8_t bleh = 0; uint8_t bleh = 0;
status = i2ctu_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK, status = i2ctu_write(cmd.flags, cmd.cmd & ITU_CMD_I2C_IO_DIR_MASK,
cmd.addr, &bleh, 0); cmd.addr, &bleh, 0);
printf("probe -> %d\n", status); //printf("probe -> %d\n", status);
return tud_control_status(rhport, req); return tud_control_status(rhport, req);
} else { } else {
// handled in DATA stage! // 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; break;
default: default:
printf("I2C-Tiny-USB: unknown command %02x\n", req->bRequest); //printf("I2C-Tiny-USB: unknown command %02x\n", req->bRequest);
return false; return false;
} }
} else return true; // other stage... } else return true; // other stage...