/** **************************************************************************************** * @brief Start a data transmission. * @param[in] saddr slave device address(7bits, without R/W bit) * @return Error code * @description * This function is used to complete an I2C write transaction from start to stop. All the intermittent steps * are handled in the interrupt handler while the interrupt is enabled. * Before this function is called, the read length, write length, I2C master buffer, * and I2C state need to be filled. Please refer to I2C_BYTE_WRITE(). * As soon as the end of the data transfer is detected, the callback function is called. ***************************************************************************************** */ static enum I2C_ERR_CODE i2c_write(uint8_t saddr) { uint32_t reg; uint32_t timeout = 0; if (i2c_bus_check() == I2C_BUS_BUSY) { return I2C_CONFLICT; } else { i2c_env.i2cOpFsm = I2C_OP_WRDATA; } // start write slave address with write bit reg = I2C_MASK_WR_EN | I2C_MASK_START | ((saddr << 1) & 0xFE); i2c_i2c_SetTXD(QN_I2C, reg); do { timeout++; if (timeout > I2C_MAX_TIMEOUT) { return I2C_TIMEOUT; } #if CONFIG_I2C_ENABLE_INTERRUPT==FALSE i2c_polling(); #endif if (i2c_env.i2cOpFsm == I2C_OP_ABORT) { return I2C_NO_ACK; } } while (i2c_env.i2cOpFsm != I2C_OP_FINISH); #if I2C_CALLBACK_EN==TRUE // Call end of transmission callback if (i2c_env.callback != NULL) { i2c_env.callback(); } #endif return I2C_NO_ERROR; }
/** **************************************************************************************** * @brief Start a data reception. * @param[in] saddr slave device address(7bits, without R/W bit) * @return Error code * @description * This function is used to complete an I2C read transaction from start to stop. All the intermittent steps * are handled in the interrupt handler while the interrupt is enabled. * Before this function is called, the read length, write length, I2C master buffer, * and I2C state need to be filled. Please refer to I2C_BYTE_READ(). * As soon as the end of the data transfer is detected, the callback function is called. ***************************************************************************************** */ static enum I2C_ERR_CODE i2c_read(uint8_t saddr) { uint32_t reg; uint32_t timeout = 0; if (i2c_bus_check() == I2C_BUS_BUSY) { return I2C_CONFLICT; } if (i2c_env.i2cTxCount) { i2c_env.i2cOpFsm = I2C_OP_SETADDR; // start write slave address with write bit reg = I2C_MASK_WR_EN | I2C_MASK_START | ((saddr << 1) & 0xFE); i2c_i2c_SetTXD(QN_I2C, reg); do { timeout++; if (timeout > I2C_MAX_TIMEOUT) { return I2C_TIMEOUT; } #if CONFIG_I2C_ENABLE_INTERRUPT==FALSE i2c_polling(); #endif if (i2c_env.i2cOpFsm == I2C_OP_ABORT) { return I2C_NO_ACK; } } while (i2c_env.i2cOpFsm != I2C_OP_RDDATA); } else { // does not need write address, directly read data from device i2c_env.i2cOpFsm = I2C_OP_RDDATA; } // start write slave address with read bit reg = I2C_MASK_WR_EN | I2C_MASK_START | ((saddr << 1) | 0x01); i2c_i2c_SetTXD(QN_I2C, reg); timeout = 0; do { timeout++; if (timeout > I2C_MAX_TIMEOUT) { return I2C_TIMEOUT; } #if CONFIG_I2C_ENABLE_INTERRUPT==FALSE i2c_polling(); #endif if (i2c_env.i2cOpFsm == I2C_OP_ABORT) { return I2C_NO_ACK; } } while (i2c_env.i2cOpFsm != I2C_OP_FINISH); #if I2C_CALLBACK_EN==TRUE // Call end of reception callback if (i2c_env.callback != NULL) { i2c_env.callback(); } #endif return I2C_NO_ERROR; }
/** **************************************************************************************** * @brief Start a data reception. * @param[in] saddr slave device address (7bits, without R/W bit) * @description * This function is used to complete an I2C read transaction from start to stop. All the intermittent steps * are handled in the interrupt handler while the interrupt is enabled. * Before this function is called, the read length, write length, I2C master buffer, * and I2C state need to be filled. Please refer to I2C_BYTE_READ(). * As soon as the end of the data transfer is detected, the callback function is called. ***************************************************************************************** */ void i2c_read(uint8_t saddr) { uint32_t reg; uint32_t timeout = 0; if (i2c_bus_check() == I2C_BUS_BUSY) { return; } if (i2c_env.i2cTxCount) { i2c_env.i2cOpFsm = I2C_OP_SETADDR; // start write slave address with write bit reg = I2C_MASK_WR_EN | I2C_MASK_START | ((saddr << 1) & 0xFE); i2c_i2c_SetTXD(QN_I2C, reg); #ifdef SLP_TEST_EN // Wait For Interrupt __WFI(); // Enter sleep mode // Wakeup when I2C interrupt is triggered #endif do { timeout++; if (timeout > I2C_MAX_TIMEOUT) { break; } #if CONFIG_I2C_ENABLE_INTERRUPT==FALSE i2c_polling(); #endif } while ((i2c_env.i2cOpFsm != I2C_OP_RDDATA)&&(i2c_env.i2cOpFsm != I2C_OP_ABORT)); } else { // does not need write address, directly read data from device i2c_env.i2cOpFsm = I2C_OP_RDDATA; } // start write slave address with read bit reg = I2C_MASK_WR_EN | I2C_MASK_START | ((saddr << 1) | 0x01); i2c_i2c_SetTXD(QN_I2C, reg); timeout = 0; do { timeout++; if (timeout > I2C_MAX_TIMEOUT){ break; } #if CONFIG_I2C_ENABLE_INTERRUPT==FALSE i2c_polling(); #endif } while (i2c_env.i2cOpFsm != I2C_OP_FINISH); #if I2C_CALLBACK_EN==TRUE // Call end of reception callback if ((i2c_env.i2cOpFsm == I2C_OP_FINISH) && (i2c_env.callback != NULL)) { i2c_env.callback(); } #endif }