Beispiel #1
0
//*****************************************************************************
//
//! 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);
}
Beispiel #2
0
//*****************************************************************************
//
//! 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);
}
Beispiel #3
0
//*****************************************************************************
//
//! 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);
}
Beispiel #4
0
//*****************************************************************************
//
//! 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);
}
Beispiel #5
0
//*****************************************************************************
//
// 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;
        }
Beispiel #6
0
//*****************************************************************************
//
// 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;
        }
    }
Beispiel #7
0
//*****************************************************************************
//
// 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;
        }
    }
Beispiel #8
0
//*****************************************************************************
//
//! 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);
}
Beispiel #9
0
//*****************************************************************************
//
// 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;
        }
Beispiel #10
0
//*****************************************************************************
//
// 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);
    }
}
Beispiel #11
0
//*****************************************************************************
//
// 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;
        }