3-Axis Digital Compass IC
HMC5883L.cpp
- Committer:
- mcm
- Date:
- 2017-10-13
- Revision:
- 4:f95da142fd3a
- Parent:
- 2:e02c2a91d2ea
File content as of revision 4:f95da142fd3a:
/** * @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; }