3-Axis Digital Compass IC

Revision:
2:e02c2a91d2ea
Parent:
0:cd8407d7155b
--- a/HMC5883L.cpp	Fri Oct 13 14:48:42 2017 +0000
+++ b/HMC5883L.cpp	Fri Oct 13 15:11:47 2017 +0000
@@ -0,0 +1,723 @@
+/**
+ * @brief       HMC5883L.h
+ * @details     3-Axis Digital Compass IC.
+ *              Functions file.
+ *
+ *
+ * @return      NA
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017    The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN
+ * @pre         This code belongs to AqueronteBlog ( http://unbarquero.blogspot.com ).
+ */
+
+#include "HMC5883L.h"
+
+
+HMC5883L::HMC5883L ( PinName sda, PinName scl, uint32_t addr, uint32_t freq )
+    : _i2c          ( sda, scl )
+    , _HMC5883L_Addr ( addr )
+{
+    _i2c.frequency( freq );
+}
+
+
+HMC5883L::~HMC5883L()
+{
+}
+
+
+
+/**
+ * @brief       HMC5883L_Conf ( HMC5883L_register_list_t , HMC5883L_conf_reg_a_samples_t , HMC5883L_conf_reg_a_dor_t , HMC5883L_conf_reg_a_measurement_mode_t
+ *                              HMC5883L_conf_reg_b_gain_t , HMC5883L_mode_register_high_speed_t , HMC5883L_mode_register_operation_mode_t )
+ *
+ * @details     It configures the device.
+ *
+ * @param[in]    mySamples:             Number of average samples.
+ * @param[in]    myDataRate:            Data output rate.
+ * @param[in]    myMeasurementMode:     Measurement mode.
+ * @param[in]    myGain:                Gain.
+ * @param[in]    myI2CMode:             I2C High Speed / Normal speed.
+ * @param[in]    myOperationMode:       Operation mode.
+ *
+ * @param[out]   NaN.
+ *
+ *
+ * @return       Status of HMC5883L_Conf.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         NaN
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_Conf ( HMC5883L_conf_reg_a_samples_t mySamples, HMC5883L_conf_reg_a_dor_t myDataRate, HMC5883L_conf_reg_a_measurement_mode_t myMeasurementMode, 
+                                                       HMC5883L_conf_reg_b_gain_t myGain, HMC5883L_mode_register_high_speed_t myI2CMode, HMC5883L_mode_register_operation_mode_t myOperationMode )
+{
+    char        cmd[]  =   { 0, 0 };
+    uint32_t    aux    =   0;
+
+
+// CONFIGURATION REGISTER A
+    cmd[0]  =    HMC5883L_CONFIGURATION_REGISTER_A;
+
+    // Number of Samples Averaged
+    cmd[1]  =   mySamples;
+
+    // Data Output Rate Bits
+    cmd[1] |=   myDataRate;
+
+    // Measurement Configuration Bits
+    cmd[1] |=   myMeasurementMode;
+
+
+    // Write the command to Configuration Register A
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 2 );
+
+
+
+// CONFIGURATION REGISTER A
+    cmd[0]  =    HMC5883L_CONFIGURATION_REGISTER_B;
+
+    // Gain Configuration Bits
+    cmd[1]  =   myGain;
+
+    // Write the command to Configuration Register B
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 2 );
+
+
+
+// MODE REGISTER
+    cmd[0]  =    HMC5883L_MODE_REGISTER;
+
+    // High Speed I2C, 3400kHz
+    cmd[1]  =   myI2CMode;
+
+    // Mode Select Bits
+    cmd[1] |=   myOperationMode;
+
+
+    // Write the command to Mode Register
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 2 );
+
+
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_GetIdentificationRegister ( HMC5883L_register_list_t , HMC5883L_vector_data_t*  )
+ *
+ * @details     It gets the identification register.
+ *
+ * @param[in]    myID_reg:          Identification register to be read.
+ *
+ * @param[out]   myID:            Identification register value.
+ *
+ *
+ * @return       Status of HMC5883L_GetIdentificationRegister.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         NaN
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_GetIdentificationRegister ( HMC5883L_register_list_t myID_reg, HMC5883L_vector_data_t* myID )
+{
+    char        cmd  =   0;
+    uint32_t    aux  =   0;
+
+
+    // Write the command
+    cmd = myID_reg;
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd, 1, true );
+
+    // Read the data
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd, 1 );
+
+
+
+    // Choose which ID was requested
+    switch ( myID_reg )
+    {
+    case HMC5883L_IDENTIFICATION_REGISTER_A:
+        myID->IdentificationRegisterA    =   cmd;
+        break;
+
+    case HMC5883L_IDENTIFICATION_REGISTER_B:
+        myID->IdentificationRegisterB    =   cmd;
+        break;
+
+    case HMC5883L_IDENTIFICATION_REGISTER_C:
+        myID->IdentificationRegisterC    =   cmd;
+        break;
+
+    default:
+        return   HMC5883L_FAILURE;
+    }
+
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_GetRawDataOutput ( HMC5883L_vector_data_t*  )
+ *
+ * @details     It gets X, Y and Z raw data output.
+ *
+ *
+ * @param[out]   myData:            X, Y and Z raw data output.
+ *
+ *
+ * @return       Status of HMC5883L_GetRawDataOutput.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         NaN
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_GetRawDataOutput ( HMC5883L_vector_data_t* myData )
+{
+    char        cmd[]  =   { HMC5883L_DATA_OUTPUT_X_MSB, 0, 0, 0, 0, 0 };
+    uint32_t    aux    =   0;
+
+
+    // Write the command
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 1, true );
+
+    // Read all data
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd[0], 6 );
+
+
+    // Parse the data
+    myData->DataOutput_X     =   ( ( int16_t )( cmd[0] << 8 ) | ( int16_t )cmd[1] );
+    myData->DataOutput_Y     =   ( ( int16_t )( cmd[2] << 8 ) | ( int16_t )cmd[3] );
+    myData->DataOutput_Z     =   ( ( int16_t )( cmd[4] << 8 ) | ( int16_t )cmd[5] );
+
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_GetCompensatedDataOutput ( HMC5883L_vector_data_t* , float , float , float )
+ *
+ * @details     It gets X, Y and Z compensated data output.
+ *
+ * @param[in]    myXOffset:         X-axis Offset.
+ * @param[in]    myYOffset:         Y-axis Offset.
+ * @param[in]    myZOffset:         Z-axis Offset.
+ *
+ * @param[out]   myData:            X, Y and Z compensated data output.
+ *
+ *
+ * @return       Status of HMC5883L_GetCompensatedDataOutput.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         The offset MUST be calculated previously, this driver does NOT support that functionality yet.
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_GetCompensatedDataOutput ( HMC5883L_vector_data_t* myData, float myXOffset, float myYOffset, float myZOffset )
+{
+    char        cmd[]    =   { 0, 0, 0, 0, 0, 0 };
+    uint32_t    aux      =   0;
+    float       myGain   =   0.0;
+
+
+
+    // GET THE CURRENT GAIN
+    cmd[0]   =   HMC5883L_CONFIGURATION_REGISTER_B;
+
+    // Write the command
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 1, true );
+
+    // Read the register
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd[0], 1 );
+
+
+    // Check which gain is in use
+    switch ( ( cmd[0] & CONF_REG_B_GAIN_MASK ) )
+    {
+    case CONF_REG_B_GAIN_0_88_GA:
+        myGain   =   0.73;
+        break;
+
+    case CONF_REG_B_GAIN_1_3_GA:
+        myGain   =   0.92;
+        break;
+
+    case CONF_REG_B_GAIN_1_9_GA:
+        myGain   =   1.22;
+        break;
+
+    case CONF_REG_B_GAIN_2_5_GA:
+        myGain   =   1.52;
+        break;
+
+    case CONF_REG_B_GAIN_4_0_GA:
+        myGain   =   2.27;
+        break;
+
+    case CONF_REG_B_GAIN_4_7_GA:
+        myGain   =   2.56;
+        break;
+
+    case CONF_REG_B_GAIN_5_6_GA:
+        myGain   =   3.03;
+        break;
+
+    case CONF_REG_B_GAIN_8_1_GA:
+        myGain   =   4.35;
+        break;
+
+    default:
+        return   HMC5883L_FAILURE;
+    }
+
+
+    // READ THE ACTUAL DATA OUTPUT
+    cmd[0]   =   HMC5883L_DATA_OUTPUT_X_MSB;
+
+    // Write the command
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 1, true );
+
+    // Read all data
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd[0], 6 );
+
+
+    // Parse the data
+    myData->DataOutput_X     =   ( ( ( int16_t )( cmd[0] << 8 ) | ( int16_t )cmd[1] ) * myGain ) - myXOffset;
+    myData->DataOutput_Y     =   ( ( ( int16_t )( cmd[2] << 8 ) | ( int16_t )cmd[3] ) * myGain ) - myYOffset;
+    myData->DataOutput_Z     =   ( ( ( int16_t )( cmd[4] << 8 ) | ( int16_t )cmd[5] ) * myGain ) - myZOffset;
+
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_GetStatus ( HMC5883L_vector_data_t*  )
+ *
+ * @details     It reads the status register.
+ *
+ * @param[in]    NaN
+ *
+ * @param[out]   myStatus:          Current status of the device.
+ *
+ *
+ * @return       Status of HMC5883L_GetStatus.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         NaN
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_GetStatus ( HMC5883L_vector_data_t* myStatus )
+{
+    char        cmd    =   HMC5883L_STATUS_REGISTER;
+    uint32_t    aux    =   0;
+
+
+    // Write the command
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd, 1, true );
+
+    // Read the status register
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd, 1 );
+
+    
+    // Update the value
+    myStatus->Status     =   cmd;
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_ReadRegister ( HMC5883L_register_list_t , uint8_t*  )
+ *
+ * @details     It reads a register.
+ *
+ * @param[in]    myRegister:        The register to be read.
+ *
+ * @param[out]   myRegisterData:    The value of the register.
+ *
+ *
+ * @return       Status of HMC5883L_ReadRegister.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         This function neither reads the OUTPUTs nor the Status register.
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_ReadRegister ( HMC5883L_register_list_t myRegister, uint8_t* myRegisterData )
+{
+    char       cmd    =   0;
+    uint8_t    aux    =   0;
+
+
+    // Only three register can be read: Configuration Register A, Configuration Register B and Mode Register
+    // NOTE: This function neither reads the OUTPUTs nor the Status register
+    if ( myRegister > HMC5883L_MODE_REGISTER )
+        return   HMC5883L_FAILURE;
+
+
+    // Write the command
+    cmd = *myRegisterData;
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd, 1, true );
+
+    // Read the register
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd, 1 );
+    
+    
+    // Update the value
+    *myRegisterData  =   cmd;
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_SetNumSample ( HMC5883L_conf_reg_a_samples_t )
+ *
+ * @details     It configures the number of samples averaged.
+ *
+ * @param[in]    mySamples:         New Number of samples averaged.
+ *
+ * @param[out]   NaN.
+ *
+ *
+ * @return       Status of HMC5883L_SetNumSample.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_SetNumSample ( HMC5883L_conf_reg_a_samples_t mySamples )
+{
+    char        cmd[]  =   { HMC5883L_CONFIGURATION_REGISTER_A, 0 };
+    uint32_t    aux    =   0;
+
+
+
+    // Write the command
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 1, true );
+
+    // Read the configuration register A
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd[1], 1 );
+
+
+    // Check if they are different, if so, update the value
+    if ( ( cmd[1] & CONF_REG_A_SAMPLE_MASK ) !=   mySamples )
+    {
+        cmd[0]  =   HMC5883L_CONFIGURATION_REGISTER_A;
+
+        // Mask [ MA1 to MA0 ] Number of Samples
+        cmd[1] &=   ~CONF_REG_A_SAMPLE_MASK;
+
+        // Update number of samples
+        cmd[1] |=   mySamples;
+
+        // Write the new value
+        aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 2 );
+    }
+
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_SetDataRate ( HMC5883L_conf_reg_a_dor_t )
+ *
+ * @details     It configures the data rate.
+ *
+ * @param[in]    myDataRate:        New data rate.
+ *
+ * @param[out]   NaN.
+ *
+ *
+ * @return       Status of HMC5883L_SetDataRate.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_SetDataRate ( HMC5883L_conf_reg_a_dor_t myDataRate )
+{
+    char        cmd[]  =   { HMC5883L_CONFIGURATION_REGISTER_A, 0 };
+    uint32_t    aux    =   0;
+
+
+
+    // Write the command
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 1, true );
+
+    // Read the configuration register A
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd[1], 1 );
+
+
+    // Check if they are different, if so, update the value
+    if ( ( cmd[1] & CONF_REG_A_DATARATE_MASK ) !=   myDataRate )
+    {
+        cmd[0]  =   HMC5883L_CONFIGURATION_REGISTER_A;
+
+        // Mask [ DO2 to DO0 ] Data Output Rate Bits
+        cmd[1] &=   ~CONF_REG_A_DATARATE_MASK;
+
+        // Update Data Output Rate Bits
+        cmd[1] |=   myDataRate;
+
+        // Write the new value
+        aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 2 );
+    }
+
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_SetMeasurementConf ( HMC5883L_conf_reg_a_measurement_mode_t )
+ *
+ * @details     It configures the measurement configuration bits.
+ *
+ * @param[in]    myMeasurementMode: New measurement mode.
+ *
+ * @param[out]   NaN.
+ *
+ *
+ * @return       Status of HMC5883L_SetMeasurementConf.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_SetMeasurementConf ( HMC5883L_conf_reg_a_measurement_mode_t myMeasurementMode )
+{
+    char        cmd[]  =   { HMC5883L_CONFIGURATION_REGISTER_A, 0 };
+    uint32_t    aux    =   0;
+
+
+
+    // Write the command
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 1, true );
+
+    // Read the configuration register A
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd[1], 1 );
+
+
+    // Check if they are different, if so, update the value
+    if ( ( cmd[1] & CONF_REG_A_MODE_MASK ) !=   myMeasurementMode )
+    {
+        cmd[0]  =   HMC5883L_CONFIGURATION_REGISTER_A;
+
+        // Mask [ MS1 to MS0 ] Measurement Configuration Bits
+        cmd[1] &=   ~CONF_REG_A_MODE_MASK;
+
+        // Update Measurement Configuration Bits
+        cmd[1] |=   myMeasurementMode;
+
+        // Write the new value
+        aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 2 );
+    }
+
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_SetGain ( HMC5883L_conf_reg_b_gain_t )
+ *
+ * @details     It configures the gain/resolution.
+ *
+ * @param[in]    myGain:            New gain/resolution.
+ *
+ * @param[out]   NaN.
+ *
+ *
+ * @return       Status of HMC5883L_SetGain.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_SetGain ( HMC5883L_conf_reg_b_gain_t myGain )
+{
+    char        cmd[]  =   { HMC5883L_CONFIGURATION_REGISTER_B , 0 };
+    uint32_t    aux    =   0;
+
+
+
+    // Write the command
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 1, true );
+
+    // Read the configuration register B
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd[1], 1 );
+
+
+    // Check if they are different, if so, update the value
+    if ( ( cmd[1] & CONF_REG_B_GAIN_MASK ) !=   myGain )
+    {
+        cmd[0]  =   HMC5883L_CONFIGURATION_REGISTER_B;
+
+        // Mask [ GN2 to GN0 ] Gain Configuration Bits
+        cmd[1] &=   ~CONF_REG_B_GAIN_MASK;
+
+        // Update Gain Configuration Bits
+        cmd[1] |=   myGain;
+
+        // Write the new value
+        aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 2 );
+    }
+
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}
+
+
+
+/**
+ * @brief       HMC5883L_SetMode ( HMC5883L_mode_register_operation_mode_t )
+ *
+ * @details     It configures the operation mode.
+ *
+ * @param[in]    myOperationMode:   New operation mode.
+ *
+ * @param[out]   NaN.
+ *
+ *
+ * @return       Status of HMC5883L_SetMode.
+ *
+ *
+ * @author      Manuel Caballero
+ * @date        13/October/2017
+ * @version     13/October/2017   The ORIGIN
+ * @pre         NaN.
+ * @warning     NaN.
+ */
+HMC5883L::HMC5883L_status_t  HMC5883L::HMC5883L_SetMode ( HMC5883L_mode_register_operation_mode_t myOperationMode )
+{
+    char        cmd[]  =   { HMC5883L_MODE_REGISTER, 0 };
+    uint32_t    aux    =   0;
+
+
+
+    // Write the command
+    aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 1, true );
+
+    // Read the Mode register bit
+    aux = _i2c.read  ( _HMC5883L_Addr, &cmd[1], 1 );
+
+
+    // Check if they are different, if so, update the value
+    if ( ( cmd[1] & MODE_REG_MODE_MASK ) !=   myOperationMode )
+    {
+        cmd[0]  =   HMC5883L_MODE_REGISTER;
+
+        // Mask [ MD1 to MD0 ] Mode Select Bits
+        cmd[1] &=   ~MODE_REG_MODE_MASK;
+
+        // Update Mode Select Bits
+        cmd[1] |=   myOperationMode;
+
+        // Write the new value
+        aux = _i2c.write ( _HMC5883L_Addr, &cmd[0], 2 );
+    }
+
+
+
+
+    if ( aux == I2C_SUCCESS )
+        return   HMC5883L_SUCCESS;
+    else
+        return   HMC5883L_FAILURE;
+}