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

Revision:
0:7864abfabe2f
Child:
1:e68ce5025dad
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LSM303DLHC.h	Mon Jun 06 07:40:45 2016 +0000
@@ -0,0 +1,182 @@
+#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); 
+        
+        //// 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
\ No newline at end of file