LSM303DLHC Full Driver: Readings For Acc, Mag and Temp; Class Method for frequently-used 13 sensor parameters; Class Method to direct modify registers; Support Calibration (offset+scale);

Dependencies:   mbed

LSM303DLHC.cpp

Committer:
Airium
Date:
2016-06-06
Revision:
0:7864abfabe2f
Child:
1:e68ce5025dad

File content as of revision 0:7864abfabe2f:

#include "mbed.h"
#include "LSM303DLHC.h"

LSM303DLHC::LSM303DLHC(PinName sda, PinName scl) : i2c(sda, scl){
    i2c.frequency(400000);
    
    HPF_state = false; // reg default value corresponds to this
    
    acc_offset[0] = 0;
    acc_offset[1] = 0;
    acc_offset[2] = 0;
    acc_scale[0] = 1;
    acc_scale[1] = 1;
    acc_scale[2] = 1;
    
    mag_offset[0] = 0;
    mag_offset[1] = 0;
    mag_offset[2] = 0;
    mag_scale[0] = 1;
    mag_scale[1] = 1;
    mag_scale[2] = 1;
    
    temp_offset[0] = 0;
    temp_scale[0] = 1;
    
    // CUSTOM THE INITIAL CTRL FOR YOURSELF
    ACtrl(LP_OFF);      // ACC Normal Power Mode
    ACtrl(ODR3);        // ACC ON and Date Rate 25Hz
    ACtrl(HPF_ON);      // ACC internal HPF In Use 
    ACtrl(HPF_CF0);     // ACC HPF Cutoff Freq = option 0    
    ACtrl(HPF_NORM);    // ACC HPF Model = Normal
    ACtrl(BDU_CONT);    // ACC data continuous
    ACtrl(G4);          // ACC Range +/-4g
    ACtrl(HIGH_R);      // ACC in High Prec
    MCtrl(DR4);         // MAG DR 15Hz
    MCtrl(GN4);         // MAG GN 4.0Gauss    
    MCtrl(MD_CONT);     // MAG ON and MD Continuous
    TCtrl(TEMP_ON);     // TEMP ON
}

void LSM303DLHC::GetAcc(float arr[3]){
    data[0] = OUT_X_L_A | (1 << 7); // MSB=1 to read multiple bytes
    i2c.write(ACC_ADDRESS, data, 1);
    i2c.read(ACC_ADDRESS, data, 6);
    
    // return the raw acceleration
    if (HPF_state == HPF_ON){ // HPF has no offset
        arr[0] = acc_scale[0]*((short)(data[1]<<8 | data[0])>>4);
        arr[1] = acc_scale[1]*((short)(data[3]<<8 | data[2])>>4);
        arr[2] = acc_scale[2]*((short)(data[5]<<8 | data[4])>>4);
    }else{
        arr[0] = acc_scale[0]*(acc_offset[0]+((short)(data[1]<<8 | data[0])>>4));
        arr[1] = acc_scale[1]*(acc_offset[1]+((short)(data[3]<<8 | data[2])>>4));
        arr[2] = acc_scale[2]*(acc_offset[2]+((short)(data[5]<<8 | data[4])>>4));
    }
}

void LSM303DLHC::GetMag(float arr[3]){
    data[0] = OUT_X_H_M;
    i2c.write(MAG_ADDRESS, data, 1);
    i2c.read(MAG_ADDRESS, data, 6);
    arr[0] = mag_scale[0]*(mag_offset[0]+(short)(data[0]<<8 | data[1]));
    arr[1] = mag_scale[1]*(mag_offset[1]+(short)(data[4]<<8 | data[5]));
    arr[2] = mag_scale[2]*(mag_offset[2]+(short)(data[2]<<8 | data[3]));
}

void LSM303DLHC::GetTemp(float arr[1]){
    data[0] = TEMP_OUT_H_M;
    i2c.write(MAG_ADDRESS, data, 1);
    i2c.read(MAG_ADDRESS, data, 2);
    arr[0] = temp_scale[0]*(temp_offset[0]+((short)(data[0]<<8 | data[1])>>4));
}

void LSM303DLHC::ACtrl(ACC_ODR cmd){
    data[0] = CTRL_REG1_A;
    i2c.write(ACC_ADDRESS, data, 1);
    i2c.read(ACC_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b00001111) | (cmd<<4);
    i2c.write(ACC_ADDRESS, data, 2);  
}

void LSM303DLHC::ACtrl(ACC_LPen cmd){
    data[0] = CTRL_REG1_A;
    i2c.write(ACC_ADDRESS, data, 1);
    i2c.read(ACC_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b11110111) | (cmd<<3);
    i2c.write(ACC_ADDRESS, data, 2); 
}

void LSM303DLHC::ACtrl(ACC_HPM cmd){
    data[0] = CTRL_REG2_A;
    i2c.write(ACC_ADDRESS, data, 1);
    i2c.read(ACC_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b00111111) | (cmd<<6);
    i2c.write(ACC_ADDRESS, data, 2); 
}

void LSM303DLHC::ACtrl(ACC_HPCF cmd){
    data[0] = CTRL_REG2_A;
    i2c.write(ACC_ADDRESS, data, 1);
    i2c.read(ACC_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b11001111) | (cmd<<4);
    i2c.write(ACC_ADDRESS, data, 2); 
}

void LSM303DLHC::ACtrl(ACC_FDS cmd){
    data[0] = CTRL_REG2_A;
    i2c.write(ACC_ADDRESS, data, 1);
    i2c.read(ACC_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b11110111) | (cmd<<3);
    i2c.write(ACC_ADDRESS, data, 2); 
    (cmd == HPF_ON)?(HPF_state = true):(HPF_state = false);
}

void LSM303DLHC::ACtrl(ACC_BDU cmd){
    data[0] = CTRL_REG4_A;
    i2c.write(ACC_ADDRESS, data, 1);
    i2c.read(ACC_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b01111111) | (cmd<<7);
    i2c.write(ACC_ADDRESS, data, 2); 
}

void LSM303DLHC::ACtrl(ACC_FS cmd){
    data[0] = CTRL_REG4_A;
    i2c.write(ACC_ADDRESS, data, 1);
    i2c.read(ACC_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b11001111) | (cmd<<4);
    i2c.write(ACC_ADDRESS, data, 2); 
}

void LSM303DLHC::ACtrl(ACC_HR cmd){
    data[0] = CTRL_REG4_A;
    i2c.write(ACC_ADDRESS, data, 1);
    i2c.read(ACC_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b11110111) | (cmd<<3);
    i2c.write(ACC_ADDRESS, data, 2); 
}

void LSM303DLHC::TCtrl(TEMP_EN cmd){
    data[0] = CRA_REG_M;
    i2c.write(MAG_ADDRESS, data, 1);
    i2c.read(MAG_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b01111111) | (cmd<<7);
    i2c.write(MAG_ADDRESS, data, 2); 
}

void LSM303DLHC::MCtrl(MAG_DR cmd){
    data[0] = CRA_REG_M;
    i2c.write(MAG_ADDRESS, data, 1);
    i2c.read(MAG_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b11100011) | (cmd<<2);
    i2c.write(MAG_ADDRESS, data, 2); 
}

void LSM303DLHC::MCtrl(MAG_GN cmd){
    data[0] = CRB_REG_M;
    i2c.write(MAG_ADDRESS, data, 1);
    i2c.read(MAG_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b00011111) | (cmd<<5);
    i2c.write(MAG_ADDRESS, data, 2); 
}

void LSM303DLHC::MCtrl(MAG_MD cmd){
    data[0] = MR_REG_M;
    i2c.write(MAG_ADDRESS, data, 1);
    i2c.read(MAG_ADDRESS, &data[1], 1);
    data[1] = data[1] & (0b11111100) | (cmd<<0);
    i2c.write(MAG_ADDRESS, data, 2); 
}

void LSM303DLHC::WriteReg(int sad, char d[2]){
    i2c.write(sad, d, 2);   
}

void LSM303DLHC::AccCal(float offset[3], float scale[3]){
    acc_offset[0] = offset[0];
    acc_offset[1] = offset[1];
    acc_offset[2] = offset[2];
    acc_scale[0] = scale[0];
    acc_scale[1] = scale[1];
    acc_scale[2] = scale[2];
}

void LSM303DLHC::MagCal(float offset[3], float scale[3]){
    mag_offset[0] = offset[0];
    mag_offset[1] = offset[1];
    mag_offset[2] = offset[2];
    mag_scale[0] = scale[0];
    mag_scale[1] = scale[1];
    mag_scale[2] = scale[2];
}

void LSM303DLHC::TempCal(float offset[1], float scale[1]){
    temp_offset[0] = offset[0];
    temp_scale[0] = scale[0];
}

bool LSM303DLHC::isHPFEn(){
    return HPF_state;
}