//***************************************************************************** // //! Reads data from SHT21 registers. //! //! \param psInst is a pointer to the SHT21 instance data. //! \param ui8Reg is the first register to read. //! \param pui8Data is a pointer to the location to store the data that is //! read. //! \param ui16Count the number of data bytes to read. //! \param pfnCallback is the function to be called when the data has been read //! (can be \b NULL if a callback is not required). //! \param pvCallbackData pointer that is passed to the callback function. //! //! This function reads a sequence of data values from consecutive registers in //! the SHT21. //! //! \return Returns 1 if the read was successfully started and 0 if it was not. // //***************************************************************************** uint_fast8_t SHT21Read(tSHT21 *psInst, uint_fast8_t ui8Reg, uint8_t *pui8Data, uint_fast16_t ui16Count, tSensorCallback *pfnCallback, void *pvCallbackData) { // // Return a failure if the SHT21 driver is not idle (in other words, there // is already an outstanding request to the SHT21). // if(psInst->ui8State != SHT21_STATE_IDLE) { return(0); } // // Save the callback information. // psInst->pfnCallback = pfnCallback; psInst->pvCallbackData = pvCallbackData; // // Move the state machine to the wait for read state. // psInst->ui8State = SHT21_STATE_READ; // // Read the requested registers from the SHT21. // psInst->uCommand.pui8Buffer[0] = ui8Reg; if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, pui8Data, ui16Count, SHT21Callback, (void *)psInst) == 0) { // // The I2C write failed, so move to the idle state and return a // failure. // psInst->ui8State = SHT21_STATE_IDLE; return(0); } // // Success. // return(1); }
//***************************************************************************** // //! Performs a read of a BQ27510G3 data register. //! //! \param psInst is a pointer to the BQ27510G3 instance data. //! \param pfnCallback is the function to be called when the data has been read //! (can be \b NULL if a callback is not required). //! \param pvCallbackData is a pointer that is passed to the callback function. //! //! This function initiates a read of the BQ27510G3 data registers. When the //! read has completed (as indicated by calling the callback function), the new //! readings can be obtained via functions like: //! //! - BQ27510G3DataTCurrentInstantaneousGetRaw() //! - BQ27510G3DataTCurrentInstantaneousGetFloat() //! //! \return Returns 1 if the read was successfully started and 0 if it was not. // //***************************************************************************** uint_fast8_t BQ27510G3DataRead(tBQ27510G3 *psInst, tSensorCallback *pfnCallback, void *pvCallbackData) { // // Return a failure if the BQ27510G3 driver is not idle (in other words, // there is already an outstanding request to the BQ27510G3). // if(psInst->ui8State != BQ27510G3_STATE_IDLE) { return(0); } // // Save the callback information. // psInst->pfnCallback = pfnCallback; psInst->pvCallbackData = pvCallbackData; // // Move the state machine to the first read state. Reads are done in three // parts based on address ranges of the information being read. // psInst->ui8State = BQ27510G3_STATE_READ_DATA_1; // // Read the requested data from the BQ27510G3. // psInst->uCommand.pui8Buffer[0] = BQ27510G3_O_AT_RATE_TTE_LSB; if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 6, BQ27510G3Callback, psInst) == 0) { // // The I2C read failed, so move to the idle state and return a failure. // psInst->ui8State = BQ27510G3_STATE_IDLE; return(0); } // // Success. // return(1); }
//***************************************************************************** // //! Reads the temperature data from the TMP100. //! //! \param psInst is a pointer to the TMP100 instance data. //! \param pfnCallback is the function to be called when the data has been read //! (can be \b NULL if a callback is not required). //! \param pvCallbackData is a pointer that is passed to the callback function. //! //! This function initiates a read of the TMP100 data registers. When the read //! has completed (as indicated by calling the callback function), the new //! readings can be obtained via: //! //! - TMP100DataTemperatureGetRaw() //! - TMP100DataTemperatureGetFloat() //! //! \return Returns 1 if the read was successfully started and 0 if it was not. // //***************************************************************************** uint_fast8_t TMP100DataRead(tTMP100 *psInst, tSensorCallback *pfnCallback, void *pvCallbackData) { // // Return a failure if the TMP100 driver is not idle (in other words, there // is already an outstanding request to the TMP100). // if(psInst->ui8State != TMP100_STATE_IDLE) { return(0); } // // Save the callback information. // psInst->pfnCallback = pfnCallback; psInst->pvCallbackData = pvCallbackData; // // Move the state machine to the wait for data read state. // psInst->ui8State = TMP100_STATE_READ; // // Read the temperature data from the TMP100. // psInst->uCommand.pui8Buffer[0] = TMP100_O_TEMP; if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 2, TMP100Callback, psInst) == 0) { // // The I2C read failed, so move to the idle state and return a failure. // psInst->ui8State = TMP100_STATE_IDLE; return(0); } // // Success. // return(1); }
//***************************************************************************** // //! Reads the temperature and humidity data from the SHT21. //! //! \param psInst is a pointer to the SHT21 instance data //! \param pfnCallback is the function to be called when the data has been read //! (can be \b NULL if a callback is not required). //! \param pvCallbackData is a pointer that is passed to the callback function. //! //! This function initiates a read of the SHT21 data registers. The user must //! first initiate a measurement by using the SHT21Write() function configured //! to write the command for a humidity or temperature measurement. In the //! case of a measurement with I2C bus hold, this function is not needed. When //! the read has completed (as indicated by callback function), the new //! readings can be obtained via: //! //! - SHT21DataTemperatureGetRaw() //! - SHT21DataTemperatureGetFloat() //! - SHT21DataHumidityGetRaw() //! - SHT21DataHumidityGetFloat() //! //! \return Returns 1 if the read was successfully started and 0 if it was not. // //***************************************************************************** uint_fast8_t SHT21DataRead(tSHT21 *psInst, tSensorCallback *pfnCallback, void *pvCallbackData) { // // Return a failure if the SHT21 driver is not idle (in other words, there // is already an outstanding request to the SHT21). // if(psInst->ui8State != SHT21_STATE_IDLE) { return(0); } // // Save the callback information. // psInst->pfnCallback = pfnCallback; psInst->pvCallbackData = pvCallbackData; // // Move the state machine to the wait for data read state. // psInst->ui8State = SHT21_STATE_READ_DATA; // // Read the data registers from the SHT21. // if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, 0, 0, psInst->pui8Data, 2, SHT21Callback, psInst) == 0) { psInst->ui8State = SHT21_STATE_IDLE; return(0); } // // Success. // return(1); }
//***************************************************************************** // // The callback function that is called when I2C transations to/from the // MPU9150 have completed. // //***************************************************************************** static void MPU9150Callback(void *pvCallbackData, uint_fast8_t ui8Status) { tMPU9150 *psInst; // // Convert the instance data into a pointer to a tMPU9150 structure. // psInst = pvCallbackData; // // If the I2C master driver encountered a failure, force the state machine // to the idle state (which will also result in a callback to propagate the // error). Except in the case that we are in the reset wait state and the // error is an address NACK. This error is handled by the reset wait // state. // if((ui8Status != I2CM_STATUS_SUCCESS) && !((ui8Status == I2CM_STATUS_ADDR_NACK) && (psInst->ui8State == MPU9150_STATE_INIT_RESET_WAIT))) { psInst->ui8State = MPU9150_STATE_IDLE; } // // Determine the current state of the MPU9150 state machine. // switch(psInst->ui8State) { // // All states that trivially transition to IDLE, and all unknown // states. // case MPU9150_STATE_READ: case MPU9150_STATE_LAST: case MPU9150_STATE_RD_DATA: default: { // // The state machine is now idle. // psInst->ui8State = MPU9150_STATE_IDLE; // // Done. // break; } // // MPU9150 Device reset was issued // case MPU9150_STATE_INIT_RESET: { // // Issue a read of the status register to confirm reset is done. // psInst->uCommand.pui8Buffer[0] = MPU9150_O_PWR_MGMT_1; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, MPU9150Callback, psInst); psInst->ui8State = MPU9150_STATE_INIT_RESET_WAIT; break; } // // Status register was read, check if reset is done before proceeding. // case MPU9150_STATE_INIT_RESET_WAIT: { // // Check the value read back from status to determine if device // is still in reset or if it is ready. Reset state for this // register is 0x40, which has sleep bit set. Device may also // respond with an address NACK during very early stages of the // its internal reset. Keep polling until we verify device is // ready. // if((psInst->pui8Data[0] != MPU9150_PWR_MGMT_1_SLEEP) || (ui8Status == I2CM_STATUS_ADDR_NACK)) { // // Device still in reset so begin polling this register. // psInst->uCommand.pui8Buffer[0] = MPU9150_O_PWR_MGMT_1; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, MPU9150Callback, psInst); // // Intentionally stay in this state to create polling effect. // } else { // // Device is out of reset, bring it out of sleep mode. // psInst->uCommand.pui8Buffer[0] = MPU9150_O_PWR_MGMT_1; psInst->uCommand.pui8Buffer[1] = MPU9150_PWR_MGMT_1_CLKSEL_XG; I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 2, MPU9150Callback, psInst); // // Update state to show we are modifing user control and // power management 1 regs. // psInst->ui8State = MPU9150_STATE_INIT_PWR_MGMT; } break; } // // Reset complete now take device out of sleep mode. // case MPU9150_STATE_INIT_PWR_MGMT: { psInst->uCommand.pui8Buffer[0] = MPU9150_O_USER_CTRL; psInst->uCommand.pui8Buffer[1] = MPU9150_USER_CTRL_I2C_MST_EN; I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 2, MPU9150Callback, psInst); // // Update state to show we are modifing user control and // power management 1 regs. // psInst->ui8State = MPU9150_STATE_INIT_USER_CTRL; break; } // // Change to power mode complete, device is ready for configuration. // case MPU9150_STATE_INIT_USER_CTRL: { // // Load index 0 with the sample rate register number. // psInst->uCommand.pui8Buffer[0] = MPU9150_O_SMPLRT_DIV; // // Set sample rate to 50 hertz. 1000 hz / (1 + 19) // psInst->uCommand.pui8Buffer[1] = 19; I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 2, MPU9150Callback, psInst); // // update state to show are in process of configuring sensors. // psInst->ui8State = MPU9150_STATE_INIT_SAMPLE_RATE_CFG; break; } // // Sensor configuration is complete. // case MPU9150_STATE_INIT_SAMPLE_RATE_CFG: { // // Write the I2C Master delay control so we only sample the AK // every 5th time that we sample accel/gyro. Delay Count itself // handled in next state. // psInst->uCommand.pui8Buffer[0] = MPU9150_O_I2C_MST_DELAY_CTRL; psInst->uCommand.pui8Buffer[1] = (MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV0_DLY_EN | MPU9150_I2C_MST_DELAY_CTRL_I2C_SLV4_DLY_EN); I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 2, MPU9150Callback, psInst); // // Update state to show we are configuring i2c slave delay between // slave events. Slave 0 and Slave 4 transaction only occur every // 5th sample cycle. // psInst->ui8State = MPU9150_STATE_INIT_I2C_SLAVE_DLY; break; } // // Master slave delay configuration complete. // case MPU9150_STATE_INIT_I2C_SLAVE_DLY: { // // Write the configuration for I2C master control clock 400khz // and wait for external sensor before asserting data ready // psInst->uCommand.pui8Buffer[0] = MPU9150_O_I2C_MST_CTRL; psInst->uCommand.pui8Buffer[1] = (MPU9150_I2C_MST_CTRL_I2C_MST_CLK_400 | MPU9150_I2C_MST_CTRL_WAIT_FOR_ES); // // Configure I2C Slave 0 for read of AK8975 (I2C Address 0x0C) // Start at AK8975 register status 1 // Read 8 bytes and enable this slave transaction // psInst->uCommand.pui8Buffer[2] = MPU9150_I2C_SLV0_ADDR_RW | 0x0C; psInst->uCommand.pui8Buffer[3] = AK8975_O_ST1; psInst->uCommand.pui8Buffer[4] = MPU9150_I2C_SLV0_CTRL_EN | 0x08; I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 5, MPU9150Callback, psInst); // // Update state. Now in process of configuring slave 0. // psInst->ui8State = MPU9150_STATE_INIT_I2C_SLAVE_0; break; } // // I2C slave 0 init complete. // case MPU9150_STATE_INIT_I2C_SLAVE_0: { // // Write the configuration for I2C Slave 4 transaction to AK8975 // 0x0c is the AK8975 address on i2c bus. // we want to write the control register with the value for a // starting a single measurement. // psInst->uCommand.pui8Buffer[0] = MPU9150_O_I2C_SLV4_ADDR; psInst->uCommand.pui8Buffer[1] = 0x0C; psInst->uCommand.pui8Buffer[2] = AK8975_O_CNTL; psInst->uCommand.pui8Buffer[3] = AK8975_CNTL_MODE_SINGLE; // // Enable the SLV4 transaction and set the master delay to // 0x04 + 1. This means the slave transactions with delay enabled // will run every fifth accel/gyro sample. // psInst->uCommand.pui8Buffer[4] = MPU9150_I2C_SLV4_CTRL_EN | 0x04; I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 5, MPU9150Callback, psInst); // // Update state. Now in the final init state. // psInst->ui8State = MPU9150_STATE_LAST; break; } // // A write just completed // case MPU9150_STATE_WRITE: { // // Set the accelerometer and gyroscope ranges to the new values. // If the register was not modified, the values will be the same so // this has no effect. // psInst->ui8AccelAfsSel = psInst->ui8NewAccelAfsSel; psInst->ui8GyroFsSel = psInst->ui8NewGyroFsSel; // // The state machine is now idle. // psInst->ui8State = MPU9150_STATE_IDLE; // // Done. // break; } // // A read-modify-write just completed // case MPU9150_STATE_RMW: { // // See if the PWR_MGMT_1 register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == MPU9150_O_PWR_MGMT_1) { // // See if a soft reset has been issued. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & MPU9150_PWR_MGMT_1_DEVICE_RESET) { // // Default range setting is +/- 2 g // psInst->ui8AccelAfsSel = 0; psInst->ui8NewAccelAfsSel = 0; // // Default range setting is +/- 250 degrees/s // psInst->ui8GyroFsSel = 0; psInst->ui8NewGyroFsSel = 0; } } // // See if the GYRO_CONFIG register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == MPU9150_O_GYRO_CONFIG) { // // Extract the FS_SEL from the GYRO_CONFIG register value. // psInst->ui8GyroFsSel = ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & MPU9150_GYRO_CONFIG_FS_SEL_M) >> MPU9150_GYRO_CONFIG_FS_SEL_S); } // // See if the ACCEL_CONFIG register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == MPU9150_O_ACCEL_CONFIG) { // // Extract the FS_SEL from the ACCEL_CONFIG register value. // psInst->ui8AccelAfsSel = ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & MPU9150_ACCEL_CONFIG_AFS_SEL_M) >> MPU9150_ACCEL_CONFIG_AFS_SEL_S); } // // The state machine is now idle. // psInst->ui8State = MPU9150_STATE_IDLE; // // Done. // break; }
//***************************************************************************** // // The callback function that is called when I2C transations to/from the KXTI9 // have completed. // //***************************************************************************** static void KXTI9Callback(void *pvCallbackData, uint_fast8_t ui8Status) { tKXTI9 *psInst; // // Convert the instance data into a pointer to a tKXTI9 structure. // psInst = pvCallbackData; // // If the I2C master driver encountered a failure, force the state machine // to the idle state (which will also result in a callback to propagate the // error). // if((ui8Status != I2CM_STATUS_SUCCESS) && (psInst->ui8State != KXTI9_STATE_INIT_WAIT)) { psInst->ui8State = KXTI9_STATE_IDLE; } // // Determine the current state of the KXTI9 state machine. // switch(psInst->ui8State) { // // All states that trivially transition to IDLE, and all unknown // states. // case KXTI9_STATE_LAST: case KXTI9_STATE_READ: default: { // // The state machine is now idle. // psInst->ui8State = KXTI9_STATE_IDLE; // // Done. // break; } case KXTI9_STATE_INIT_RES: { // // Try to read back to determine if reset is done. We expect to see // a NAK. // psInst->uCommand.pui8Buffer[0] = KXTI9_O_CTRL3; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, KXTI9Callback, psInst); psInst->ui8State = KXTI9_STATE_INIT_WAIT; break; } case KXTI9_STATE_INIT_WAIT: { // // Check to see if there was finally an ACK. // if(ui8Status != I2CM_STATUS_SUCCESS) { // // Read again. // psInst->uCommand.pui8Buffer[0] = KXTI9_O_CTRL3; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, KXTI9Callback, psInst); } else { // // Check the read data to make sure it jibes. // if(psInst->pui8Data[0] == 0x4d) { // // Device is out of reset, enable the device. // psInst->uCommand.pui8Buffer[0] = KXTI9_O_CTRL1; psInst->uCommand.pui8Buffer[1] = KXTI9_CTRL1_PC1; I2CMWrite(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 2, KXTI9Callback, psInst); } else { ui8Status = I2CM_STATUS_ERROR; } // // This is the last init write. // psInst->ui8State = KXTI9_STATE_LAST; } break; } case KXTI9_STATE_WRITE: { // // Set the accelerometer range and resolution to the new value. // If the register was not modified, the values will be the same so // this has no effect. // psInst->ui8Resolution = psInst->ui8NewResolution; psInst->ui8Range = psInst->ui8NewRange; // // The state machine is now idle. // psInst->ui8State = KXTI9_STATE_IDLE; break; } case KXTI9_STATE_RMW: { // // See if the CTRL3 register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == KXTI9_O_CTRL3) { // // See if a soft reset has been issued. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & KXTI9_CTRL3_SRST) { // // Default range setting is +/- 2 g // psInst->ui8Range = 0; psInst->ui8NewRange = 0; // // Default resolution is 8-bit. // psInst->ui8Resolution = 0; psInst->ui8NewResolution = 0; } } // // See if the CTRL1 register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == KXTI9_O_CTRL1) { // // Extract the range and resolution from the register value. // psInst->ui8Range = ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & KXTI9_CTRL1_GSEL_M) >> KXTI9_CTRL1_GSEL_S); psInst->ui8Resolution = ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & KXTI9_CTRL1_RES) >> 6); } // // The state machine is now idle. // psInst->ui8State = KXTI9_STATE_IDLE; break; } }
//***************************************************************************** // // The callback function that is called when I2C transations to/from the // L3GD20H have completed. // //***************************************************************************** static void L3GD20HCallback(void *pvCallbackData, uint_fast8_t ui8Status) { tL3GD20H *psInst; // // Convert the instance data into a pointer to a tL3GD20H structure. // psInst = pvCallbackData; // // If the I2C master driver encountered a failure, force the state machine // to the idle state (which will also result in a callback to propagate the // error). // if(ui8Status != I2CM_STATUS_SUCCESS) { psInst->ui8State = L3GD20H_STATE_IDLE; } // // Determine the current state of the L3GD20H state machine. // switch(psInst->ui8State) { // // All states that trivially transition to IDLE, and all unknown // states. // case L3GD20H_STATE_READ: default: { // // The state machine is now idle. // psInst->ui8State = L3GD20H_STATE_IDLE; // // Done. // break; } // // L3GD20H Device reset was issued // case L3GD20H_STATE_INIT_RES: { // // Issue a read of the status register to confirm reset is done. // psInst->uCommand.pui8Buffer[0] = L3GD20H_O_LOW_ODR; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, L3GD20HCallback, psInst); psInst->ui8State = L3GD20H_STATE_INIT_WAIT; // // Done. // break; } // // Status register was read, check if reset is done before proceeding. // case L3GD20H_STATE_INIT_WAIT: { // // Check the value read back from status to determine if device // is still in reset or if it is ready. // if(psInst->pui8Data[0] & L3GD20H_LOW_ODR_SWRESET_M) { // // Device still in reset so begin polling this register. // psInst->uCommand.pui8Buffer[0] = L3GD20H_O_LOW_ODR; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, L3GD20HCallback, psInst); } else { // // Device is out of reset, move to the idle state. // psInst->ui8State = L3GD20H_STATE_IDLE; } // // Done. // break; } // // A write just completed // case L3GD20H_STATE_WRITE: { // // Set the gyroscope ranges to the new values. If the register was // not modified, the values will be the same so this has no effect. // psInst->ui8GyroFsSel = psInst->ui8NewGyroFsSel; // // The state machine is now idle. // psInst->ui8State = L3GD20H_STATE_IDLE; // // Done. // break; } // // A read-modify-write just completed // case L3GD20H_STATE_RMW: { // // See if the PWR_MGMT_1 register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == L3GD20H_O_LOW_ODR) { // // See if a soft reset has been issued. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & L3GD20H_LOW_ODR_SWRESET_M) { // // Default range setting is +/- 245 degrees/s // psInst->ui8GyroFsSel = 0; psInst->ui8NewGyroFsSel = 0; } } // // See if the GYRO_CONFIG register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == L3GD20H_O_CTRL4) { // // Extract the FS_SEL from the GYRO_CONFIG register value. // psInst->ui8GyroFsSel = ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & L3GD20H_CTRL4_FS_M) >> L3GD20H_CTRL4_FS_S); } // // The state machine is now idle. // psInst->ui8State = L3GD20H_STATE_IDLE; // // Done. // break; } }
//***************************************************************************** // //! Reads data from TMP100 registers. //! //! \param psInst is a pointer to the TMP100 instance data. //! \param ui8Reg is the first register to read. //! \param pui16Data is a pointer to the location to store the data that is //! read. //! \param ui16Count the number of register values to read. //! \param pfnCallback is the function to be called when data read is complete //! (can be \b NULL if a callback is not required). //! \param pvCallbackData is a pointer that is passed to the callback function. //! //! This function reads a sequence of data values from consecutive registers in //! the TMP100. //! //! \note The TMP100 does not auto-increment the register pointer, so reads of //! more than one value returns garbage for the subsequent values. //! //! \return Returns 1 if the write was successfully started and 0 if it was //! not. // //***************************************************************************** uint_fast8_t TMP100Read(tTMP100 *psInst, uint_fast8_t ui8Reg, uint16_t *pui16Data, uint_fast16_t ui16Count, tSensorCallback *pfnCallback, void *pvCallbackData) { // // Return a failure if the TMP100 driver is not idle (in other words, there // is already an outstanding request to the TMP100). // if(psInst->ui8State != TMP100_STATE_IDLE) { return(0); } // // Save the callback information. // psInst->pfnCallback = pfnCallback; psInst->pvCallbackData = pvCallbackData; // // Move the state machine to the wait for read state. // psInst->ui8State = TMP100_STATE_READ; // // Read the requested registers from the TMP100. // if(ui8Reg == TMP100_O_CONFIG) { // // The configuration register is only one byte, so only a single byte // read is necessary and no endian swapping is required. // psInst->uCommand.pui8Buffer[0] = ui8Reg; if(I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, (uint8_t *)pui16Data, 1, TMP100Callback, psInst) == 0) { // // The I2C write failed, so move to the idle state and return a // failure. // psInst->ui8State = TMP100_STATE_IDLE; return(0); } } else { // // This is one of the temperature registers, which are 16-bit // big-endian registers. // if(I2CMRead16BE(&(psInst->uCommand.sReadState), psInst->psI2CInst, psInst->ui8Addr, ui8Reg, pui16Data, ui16Count, TMP100Callback, psInst) == 0) { // // The I2C write failed, so move to the idle state and return a // failure. // psInst->ui8State = TMP100_STATE_IDLE; return(0); } } // // Success. // return(1); }
//***************************************************************************** // // The callback function that is called when I2C transations to/from the // MPU6050 have completed. // //***************************************************************************** static void MPU6050Callback(void *pvCallbackData, uint_fast8_t ui8Status) { tMPU6050 *psInst; // // Convert the instance data into a pointer to a tMPU6050 structure. // psInst = pvCallbackData; // // If the I2C master driver encountered a failure, force the state machine // to the idle state (which will also result in a callback to propagate the // error). Except in the case that we are in the reset wait state and the // error is an address NACK. This error is handled by the reset wait // state. // if((ui8Status != I2CM_STATUS_SUCCESS) && !((ui8Status == I2CM_STATUS_ADDR_NACK) && (psInst->ui8State == MPU6050_STATE_INIT_WAIT))) { psInst->ui8State = MPU6050_STATE_IDLE; } // // Determine the current state of the MPU6050 state machine. // switch(psInst->ui8State) { // // All states that trivially transition to IDLE, and all unknown // states. // case MPU6050_STATE_READ: default: { // // The state machine is now idle. // psInst->ui8State = MPU6050_STATE_IDLE; // // Done. // break; } // // MPU6050 Device reset was issued // case MPU6050_STATE_INIT_RES: { // // Issue a read of the status register to confirm reset is done. // psInst->uCommand.pui8Buffer[0] = MPU6050_O_PWR_MGMT_1; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, MPU6050Callback, psInst); psInst->ui8State = MPU6050_STATE_INIT_WAIT; break; } // // Status register was read, check if reset is done before proceeding. // case MPU6050_STATE_INIT_WAIT: { // // Check the value read back from status to determine if device // is still in reset or if it is ready. Reset state for this // register is 0x40, which has sleep bit set. Device may also // respond with an address NACK during very early stages of the its // internal reset. Keep polling until we verify device is ready. // // if((psInst->pui8Data[0] != MPU6050_PWR_MGMT_1_SLEEP) || (ui8Status == I2CM_STATUS_ADDR_NACK)) { // // Device still in reset so begin polling this register. // psInst->uCommand.pui8Buffer[0] = MPU6050_O_PWR_MGMT_1; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data, 1, MPU6050Callback, psInst); // // Intentionally stay in this state to create polling effect. // } else { // // Device is out of reset, move to the idle state. // psInst->ui8State = MPU6050_STATE_IDLE; } break; } // // A write just completed // case MPU6050_STATE_WRITE: { // // Set the accelerometer and gyroscope ranges to the new values. // If the register was not modified, the values will be the same so // this has no effect. // psInst->ui8AccelAfsSel = psInst->ui8NewAccelAfsSel; psInst->ui8GyroFsSel = psInst->ui8NewGyroFsSel; // // The state machine is now idle. // psInst->ui8State = MPU6050_STATE_IDLE; // // Done. // break; } // // A read-modify-write just completed // case MPU6050_STATE_RMW: { // // See if the PWR_MGMT_1 register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == MPU6050_O_PWR_MGMT_1) { // // See if a soft reset has been issued. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & MPU6050_PWR_MGMT_1_DEVICE_RESET) { // // Default range setting is +/- 2 g // psInst->ui8AccelAfsSel = 0; psInst->ui8NewAccelAfsSel = 0; // // Default range setting is +/- 250 degrees/s // psInst->ui8GyroFsSel = 0; psInst->ui8NewGyroFsSel = 0; } } // // See if the GYRO_CONFIG register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == MPU6050_O_GYRO_CONFIG) { // // Extract the FS_SEL from the GYRO_CONFIG register value. // psInst->ui8GyroFsSel = ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & MPU6050_GYRO_CONFIG_FS_SEL_M) >> MPU6050_GYRO_CONFIG_FS_SEL_S); } // // See if the ACCEL_CONFIG register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == MPU6050_O_ACCEL_CONFIG) { // // Extract the FS_SEL from the ACCEL_CONFIG register value. // psInst->ui8AccelAfsSel = ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & MPU6050_ACCEL_CONFIG_AFS_SEL_M) >> MPU6050_ACCEL_CONFIG_AFS_SEL_S); } // // The state machine is now idle. // psInst->ui8State = MPU6050_STATE_IDLE; // // Done. // break; }
//***************************************************************************** // // The callback function that is called when I2C transactions to/from the // BQ27510G3 have completed. // //***************************************************************************** static void BQ27510G3Callback(void *pvCallbackData, uint_fast8_t ui8Status) { tBQ27510G3 *psInst; // // Convert the instance data into a pointer to a tBQ27510G3 structure. // psInst = pvCallbackData; // // If the I2C master driver encountered a failure, force the state machine // to the idle state (which will also result in a callback to propagate the // error). // if(ui8Status != I2CM_STATUS_SUCCESS) { psInst->ui8State = BQ27510G3_STATE_IDLE; } // // Determine the current state of the BQ27510G3 state machine. // switch(psInst->ui8State) { // // The first data read state, has finished setup and trigger data read // state 2. // case BQ27510G3_STATE_READ_DATA_1: { // // Move the state machine to the next read state. // psInst->ui8State = BQ27510G3_STATE_READ_DATA_2; // // Read the requested data from the BQ27510G3. // psInst->uCommand.pui8Buffer[0] = BQ27510G3_O_NOM_AV_CAP_LSB; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data + 6, 24, BQ27510G3Callback, psInst); // // break // break; } // // The 2nd data read state, has finished setup and trigger data read // state 3. Read state 3 is the final state and when done will return // to idle and trigger the application level callback. // case BQ27510G3_STATE_READ_DATA_2: { // // Move the state machine to the next read state. // psInst->ui8State = BQ27510G3_STATE_READ_DATA_3; // // Read the requested data from the BQ27510G3. // psInst->uCommand.pui8Buffer[0] = BQ27510G3_O_INT_TEMP_LSB; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->uCommand.pui8Buffer, 1, psInst->pui8Data + 30, 2, BQ27510G3Callback, psInst); // // break // break; } // // All states that trivially transition to IDLE, and all unknown // states. // case BQ27510G3_STATE_INIT: case BQ27510G3_STATE_READ: case BQ27510G3_STATE_WRITE: case BQ27510G3_STATE_READ_DATA_3: case BQ27510G3_STATE_RMW: default: { // // The state machine is now idle. // psInst->ui8State = BQ27510G3_STATE_IDLE; // // Done. // break; } } // // See if the state machine is now idle and there is a callback function. // if((psInst->ui8State == BQ27510G3_STATE_IDLE) && psInst->pfnCallback) { // // Call the application-supplied callback function. // psInst->pfnCallback(psInst->pvCallbackData, ui8Status); } }
//***************************************************************************** // // The callback function that is called when I2C transations to/from the // LSM303D have completed. // //***************************************************************************** static void LSM303DCallback(void *pvCallbackData, uint_fast8_t ui8Status) { tLSM303D *psInst; // // Convert the instance data into a pointer to a tLSM303D structure. // psInst = pvCallbackData; // // If the I2C master driver encountered a failure, force the state machine // to the idle state (which will also result in a callback to propagate the // error). // if(ui8Status != I2CM_STATUS_SUCCESS) { psInst->ui8State = LSM303D_STATE_IDLE; } // // Determine the current state of the LSM303D state machine. // switch(psInst->ui8State) { // // All states that trivially transition to IDLE, and all unknown // states. // default: { // // The state machine is now idle. // psInst->ui8State = LSM303D_STATE_IDLE; // // Done. // break; } case LSM303D_STATE_READ_MAG: { // // Move the state machine to the wait for accel data read state. // psInst->ui8State = LSM303D_STATE_READ_ACCEL; // // Read the accel data registers from the LSM303D. // psInst->pui8DataAccel[0] = LSM303D_O_STATUS | 0x80; I2CMRead(psInst->psI2CInst, psInst->ui8Addr, psInst->pui8DataAccel, 1, psInst->pui8DataAccel, 7, LSM303DCallback, psInst); // // Done. // break; } case LSM303D_STATE_INIT: { psInst->ui8State = LSM303D_STATE_IDLE; // // Done. // break; } // // A write just completed // case LSM303D_STATE_WRITE: { // // Set the accelerometer ranges to the new values. If the register // was not modified, the values will be the same so this has no // effect. // psInst->ui8AccelFSSel = psInst->ui8NewAccelFSSel; psInst->ui8MagFSSel = psInst->ui8NewMagFSSel; // // The state machine is now idle. // psInst->ui8State = LSM303D_STATE_IDLE; // // Done. // break; } // // A read-modify-write just completed // case LSM303D_STATE_RMW: { // // See if the accel scale register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == LSM303D_O_CTRL2) { // // Extract the FS_SEL from the ACCEL_CONFIG register value. // psInst->ui8AccelFSSel = ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & LSM303D_CTRL2_AFS_M) >> LSM303D_CTRL2_AFS_S); } // // See if the mag scale register was just modified. // if(psInst->uCommand.sReadModifyWriteState.pui8Buffer[0] == LSM303D_O_CTRL6) { // // Extract the FS_SEL from the mag scale register value. // psInst->ui8MagFSSel = ((psInst->uCommand.sReadModifyWriteState.pui8Buffer[1] & LSM303D_CTRL6_MFS_M) >> LSM303D_CTRL6_MFS_S); } // // The state machine is now idle. // psInst->ui8State = LSM303D_STATE_IDLE; // // Done. // break; }