diff options
-rw-r--r-- | include/osmo-fl2k.h | 35 | ||||
-rw-r--r-- | src/libosmo-fl2k.c | 101 |
2 files changed, 136 insertions, 0 deletions
diff --git a/include/osmo-fl2k.h b/include/osmo-fl2k.h index 8d3cc3b..02ad4ad 100644 --- a/include/osmo-fl2k.h +++ b/include/osmo-fl2k.h @@ -37,6 +37,7 @@ enum fl2k_error { FL2K_ERROR_NO_DEVICE = -2, FL2K_ERROR_NOT_FOUND = -5, FL2K_ERROR_BUSY = -6, + FL2K_ERROR_TIMEOUT = -7, FL2K_ERROR_NO_MEM = -11, }; @@ -121,6 +122,40 @@ FL2K_API int fl2k_start_tx(fl2k_dev_t *dev, fl2k_tx_cb_t cb, */ FL2K_API int fl2k_stop_tx(fl2k_dev_t *dev); +/*! + * Read 4 bytes via the FL2K I2C bus + * + * \param dev the device handle given by fl2k_open() + * \param i2c_addr address of the I2C device + * \param reg_addr start address of the 4 bytes to be read + * \param data pointer to byte array of size 4 + * \return 0 on success + * \note A read operation will look like this on the bus: + * START, I2C_ADDR(W), REG_ADDR, REP_START, I2C_ADDR(R), DATA[0], STOP + * START, I2C_ADDR(W), REG_ADDR+1, REP_START, I2C_ADDR(R), DATA[1], STOP + * START, I2C_ADDR(W), REG_ADDR+2, REP_START, I2C_ADDR(R), DATA[2], STOP + * START, I2C_ADDR(W), REG_ADDR+3, REP_START, I2C_ADDR(R), DATA[3], STOP + */ +FL2K_API int fl2k_i2c_read(fl2k_dev_t *dev, uint8_t i2c_addr, + uint8_t reg_addr, uint8_t *data); + +/*! + * Write 4 bytes via the FL2K I2C bus + * + * \param dev the device handle given by fl2k_open() + * \param i2c_addr address of the I2C device + * \param reg_addr start address of the 4 bytes to be written + * \param data pointer to byte array of size 4 + * \return 0 on success + * \note A write operation will look like this on the bus: + * START, I2C_ADDR(W), REG_ADDR, DATA[0], STOP + * START, I2C_ADDR(W), REG_ADDR+1, DATA[1], STOP + * START, I2C_ADDR(W), REG_ADDR+2, DATA[2], STOP + * START, I2C_ADDR(W), REG_ADDR+3, DATA[3], STOP + */ +FL2K_API int fl2k_i2c_write(fl2k_dev_t *dev, uint8_t i2c_addr, + uint8_t reg_addr, uint8_t *data); + #ifdef __cplusplus } #endif diff --git a/src/libosmo-fl2k.c b/src/libosmo-fl2k.c index 34b854e..1112539 100644 --- a/src/libosmo-fl2k.c +++ b/src/libosmo-fl2k.c @@ -985,3 +985,104 @@ int fl2k_stop_tx(fl2k_dev_t *dev) return FL2K_ERROR_BUSY; } + +int fl2k_i2c_read(fl2k_dev_t *dev, uint8_t i2c_addr, uint8_t reg_addr, uint8_t *data) +{ + int i, r, timeout = 1; + uint32_t reg; + + if (!dev) + return FL2K_ERROR_INVALID_PARAM; + + r = fl2k_read_reg(dev, 0x8020, ®); + if (r < 0) + return r; + + /* apply mask, clearing bit 30 disables periodic repetition of read */ + reg &= 0x3ffc0000; + + /* set I2C register and address, select I2C read (bit 7) */ + reg |= (1 << 28) | (reg_addr << 8) | (1 << 7) | (i2c_addr & 0x7f); + + r = fl2k_write_reg(dev, 0x8020, reg); + if (r < 0) + return r; + + for (i = 0; i < 10; i++) { + sleep_ms(10); + + r = fl2k_read_reg(dev, 0x8020, ®); + if (r < 0) + return r; + + /* check if operation completed */ + if (reg & (1 << 31)) { + timeout = 0; + break; + } + } + + if (timeout) + return FL2K_ERROR_TIMEOUT; + + /* check if slave responded and all data was read */ + if (reg & (0x0f << 24)) + return FL2K_ERROR_NOT_FOUND; + + /* read data from register 0x8024 */ + return libusb_control_transfer(dev->devh, CTRL_IN, 0x40, + 0, 0x8024, data, 4, CTRL_TIMEOUT); +} + +int fl2k_i2c_write(fl2k_dev_t *dev, uint8_t i2c_addr, uint8_t reg_addr, uint8_t *data) +{ + int i, r, timeout = 1; + uint32_t reg; + + if (!dev) + return FL2K_ERROR_INVALID_PARAM; + + /* write data to register 0x8028 */ + r = libusb_control_transfer(dev->devh, CTRL_OUT, 0x41, + 0, 0x8028, data, 4, CTRL_TIMEOUT); + + if (r < 0) + return r; + + r = fl2k_read_reg(dev, 0x8020, ®); + if (r < 0) + return r; + + /* apply mask, clearing bit 30 disables periodic repetition of read */ + reg &= 0x3ffc0000; + + /* set I2C register and address */ + reg |= (1 << 28) | (reg_addr << 8) | (i2c_addr & 0x7f); + + r = fl2k_write_reg(dev, 0x8020, reg); + if (r < 0) + return r; + + for (i = 0; i < 10; i++) { + sleep_ms(10); + + r = fl2k_read_reg(dev, 0x8020, ®); + if (r < 0) + return r; + + /* check if operation completed */ + if (reg & (1 << 31)) { + timeout = 0; + break; + } + } + + if (timeout) + return FL2K_ERROR_TIMEOUT; + + /* check if slave responded and all data was written */ + if (reg & (0x0f << 24)) + return FL2K_ERROR_NOT_FOUND; + + return FL2K_SUCCESS; +} |