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.h

Committer:
Airium
Date:
2016-06-07
Revision:
1:e68ce5025dad
Parent:
0:7864abfabe2f
Child:
2:192a6c228644

File content as of revision 1:e68ce5025dad:

#ifndef LSM303DLHC_H
#define LSM303DLHC_H
#include "mbed.h"
// ACC SAD
#define ACC_ADDRESS       0x32
// ACC CTRL SUB
#define CTRL_REG1_A       0x20 //RW ODR(4) LPen Zen Yen Xen
#define CTRL_REG2_A       0x21 //RW HPM(2) HPCF(2) FDS HPCLICK HPIS2 HPIS1
#define CTRL_REG3_A       0x22 //RW I1_CLICK I1_AOI1 I1_AOI2 I1_DRDY1 I1_DRDY2 I1_WTM I1_OVERRUN -
#define CTRL_REG4_A       0x23 //RW BDU BLE FS1 FS0 HR 0(2) SIM
#define CTRL_REG5_A       0x24 //RW BOOT FIFO_EN - - LIR_INT1 D4D_INT1 LIR_INT2 D4D_INT2
#define CTRL_REG6_A       0x25 //RW I2_CLICKen I2_INT1 I2_INT2 BOOT_I1 P2_ACT - H_LACTIVE -
#define REFERENCE_A       0x26 //RW Ref7 Ref6 Ref5 Ref4 Ref3 Ref2 Ref1 Ref0
#define STATUS_REG_A      0x27 //R  ZYXOR ZOR YOR XOR ZYXDA ZDA YDA XDA
// ACC OUT SUB
#define OUT_X_L_A         0x28 //R MSB(8)
#define OUT_X_H_A         0x29 //R LSB(4) 0(4)
#define OUT_Y_L_A         0x2A //R ditto
#define OUT_Y_H_A         0x2B //R ditto
#define OUT_Z_L_A         0x2C //R ditto
#define OUT_Z_H_A         0x2D //R ditto
// ACC INT SUB
#define INT1_CFG_A        0x30 
#define INT1_SRC_A        0x31
#define INT1_THS_A        0x32
#define INT1_DURATION_A   0x33
#define INT2_CFG_A        0x34
#define INT2_SRC_A        0x35
#define INT2_THS_A        0x36
#define INT2_DURATION_A   0x37
// ACC CLICK SUB
#define CLICK_CFG_A       0x38 
#define CLICK_SRC_A       0x39 
#define CLICK_THS_A       0x3A 
#define TIME_LIMIT_A      0x3B 
#define TIME_LATENCY_A    0x3C 
#define TIME_WINDOW_A     0x3D 

// MAG SAD
#define MAG_ADDRESS       0x3C 
// MAG CTRL SUB
#define CRA_REG_M         0x00 //RW TEMP_EN 0(2) DR(3) 0(2)
#define CRB_REG_M         0x01 //RW GN(3) 0(5)
#define MR_REG_M          0x02 //RW 0(6) MD(2)
// MAG OUT SUB
#define OUT_X_H_M         0x03 //R LSB(8)
#define OUT_X_L_M         0x04 //R 0(4) MSB(4)
#define OUT_Z_H_M         0x05 //R ditto
#define OUT_Z_L_M         0x06 //R ditto
#define OUT_Y_H_M         0x07 //R ditto
#define OUT_Y_L_M         0x08 //R ditto
#define SR_REG_M          0x09 //R -(6) LOCK DRDY
#define IRA_REG_M         0x0A //R
#define IRB_REG_M         0x0B //R
#define IRC_REG_M         0x0C //R
// Temprature OUT SUB
#define TEMP_OUT_H_M      0x31 //R MSB(8)
#define TEMP_OUT_L_M      0x32 //R LSB(4) 0(4)

class LSM303DLHC {
    public:
        //// PORT
        LSM303DLHC(PinName sda, PinName scl);
        
        //// REG CTRL
        // modify the default in LSM303DLHC.cpp
        
        //// CTRL_REG1_A (20h)
        // ACC Low Power Mode ON/OFF
        enum ACC_LPen { LP_OFF = 0, LP_ON = 1} ;
        void ACtrl(ACC_LPen cmd); 
        // ACC Data Rate        NOTE: ACC SWITCH IS HERE
        enum ACC_ODR { PW_D = 0, ODR1 = 1, ODR2 = 2, ODR3 = 3, ODR4 = 4, 
             //        PW Down   1Hz       10Hz      25Hz      50Hz     
                       ODR5 = 5, ODR6 = 6,  ODR7 = 7, ODR8 = 8, ODR9 = 9};
             //        100Hz     200Hz      400Hz     1620Hz@LP 1344Hz@NM/5376HZ@LP
        void ACtrl(ACC_ODR cmd); 
        // ACC AXIS SEL
        enum ACC_AXIS { NONE = 0, X = 1, Y = 2, XY = 3, Z = 4, XZ = 5, XY = 6, XYZ = 7 };
        void ACtrl(ACC_AXIS cmd);
        
        //// CTRL_REG2_A (21h)
        // ACC HPF Mode
        enum ACC_HPM { HPF_NORM_R = 0, HPF_REF = 1, HPF_NORM = 2, HPF_AUTO = 3 };
        void ACtrl(ACC_HPM cmd);
        // ACC HPF Cutoff Freq             
        enum ACC_HPCF { HPF_CF0 = 0, HPF_CF1 = 1, HPF_CF2 = 2, HPF_CF3 = 3};
        void ACtrl(ACC_HPCF cmd);
        // ACC HPF ON/OFF for output
        enum ACC_FDS { HPF_OFF = 0, HPF_ON = 1 };                                 
        void ACtrl(ACC_FDS cmd);     
                
        //// CTRL_REG4_A (23h)
        // ACC Block Date Update Mode
        enum ACC_BDU { BDU_CONT = 0, BDU_HOLD = 1 };
        void ACtrl(ACC_BDU cmd); 
        // ACC Output Full-Scale SEL    
        enum ACC_FS {G2 = 0b00, G4 = 0b01, G8 = 0b10, G16= 0b11 }; 
             //      +/-2g      +/-4g      +/-8g      +/-16g 
        void ACtrl(ACC_FS cmd);
        // ACC Output in High/Low Resolution (Precision SEL)      
        enum ACC_HR { LOW_R = 0, HIGH_R = 1 }; 
             //       10bit      12bit
        void ACtrl(ACC_HR cmd);
                
        //// CRA_REG_M (00h)
        // TEMP Sensor En       NOTE: TEMP SWITCH IS HERE
        enum TEMP_EN { TEMP_OFF = 0, TEMP_ON = 1};
        void TCtrl(TEMP_EN cmd);       
        // MAG Data Rate (Note: MAG_DR determines DRDY pin)
        enum MAG_DR { DR0 = 0, DR1 = 1, DR2 = 2, DR3 = 3, 
             //       0.75Hz   1.5Hz    3Hz      7.5Hz      
                      DR4 = 4, DR5 = 5, DR6 = 6, DR7 = 7};
             //       15Hz     30Hz     75Hz     220Hz
        void MCtrl(MAG_DR cmd);     // MAG Date Rate
                
        //// CRB_REG_M (01h)
        // MAG Gain (Range SEL)
        enum MAG_GN { GN1 = 1, GN2 = 2, GN3 = 3, GN4 = 4, 
             //       1.3      1.9      2.5      4.0      (+/- Gauss)
                      GN5 = 5, GN6 = 6, GN7 = 7};
             //       4.7      5.6      8.1               (+/- Gauss)
        void MCtrl(MAG_GN cmd);     // MAG Measure Range
                
        //// MR_REG_M (02h)
        // MAG Mode     NOTE: MAG SWITCH IS HERE
        enum MAG_MD { MD_CONT = 0, MD_SING = 1, MD_SLP = 2, MD_SLP2 = 3}; 
             //       Continuous   single-conv  sleep-mode  sleep-mode
        void MCtrl(MAG_MD cmd);     

        //// Change more regs        
        void WriteReg(int sad, char d[2]); // Write value to reg
        // CAUTION: THE FUNTION USES UNFRIENDLY ASSIGN
        // CAUTION: WRITING TO RESERVED REG MAY CAUSE PERMANENT DAMAGE
        // PLEASE FOLLOW DATASHEET RIGIDLY        
        // sad = ACC_ADDRESS or MAG_ADDRESS
        // d[0] = Register Address
        // d[1] = Register Value

        //// Get Data
        void GetAcc(float arr[3]);  // Get acceleration using current HPF setting
        // range -2048 ~ +2047
        void GetMag(float arr[3]);  // Get magnetic flux density
        // range -2048 to 2047
        void GetTemp(float arr[1]); // Get temperature
        // range -2048 to 2047        
        
        //// sensor reading calibration        
        void AccCal(float offset[3], float scale[3]); // Acc Calibration
        // affect the reading by output = scale * ( offset + original )
        // but if internal HPF enable then output = scale * original
        void MagCal(float offset[3], float scale[3]); // Mag Calibration
        // affect the reading by output = scale * ( offset + original )
        void TempCal(float offset[1], float scale[1]); // Mag Calibration
        // affect the reading by output = scale * ( offset + original )      
        
        //// Other functions
        bool isHPFEn(); // report HPF ON/OFF state for output
        // return HPF_state
        
        //// Not implemented function
        bool isAccRdy(); // Check if acc has new data 
        // one way is to use high freq ticker to check STATUS_REG_A (27h)
        // I2C@400kHz just enough to check Max Normal Mode Data Rate (1344Hz)
        bool isMagRdy(); // check if mag has new data
        // one way is to use InterruptIn to trigger from DRDY pin
        // DRDY pin freq defined by MAG_DR
        
    private:
        I2C i2c;
        char data[6];       // used as main data exchange
        bool HPF_state;     // state of internal HPF
               
        // use offset to calibrate zero reading
        float acc_offset[3];
        float mag_offset[3];
        float temp_offset[1];
        
        //use scale to adjust the range to required
        float acc_scale[3];
        float mag_scale[3];
        float temp_scale[1];
};

#endif