AHRS Library

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LSM9DS1.cpp Source File

LSM9DS1.cpp

00001 /******************************************************************************
00002 SFE_LSM9DS1.cpp
00003 SFE_LSM9DS1 Library Source File
00004 Jim Lindblom @ SparkFun Electronics
00005 Original Creation Date: February 27, 2015
00006 https://github.com/sparkfun/LSM9DS1_Breakout
00007 
00008 This file implements all functions of the LSM9DS1 class. Functions here range
00009 from higher level stuff, like reading/writing LSM9DS1 registers to low-level,
00010 hardware reads and writes. Both SPI and I2C handler functions can be found
00011 towards the bottom of this file.
00012 
00013 Development environment specifics:
00014     IDE: Arduino 1.6
00015     Hardware Platform: Arduino Uno
00016     LSM9DS1 Breakout Version: 1.0
00017 
00018 This code is beerware; if you see me (or any other SparkFun employee) at the
00019 local, and you've found our code helpful, please buy us a round!
00020 
00021 Distributed as-is; no warranty is given.
00022 ******************************************************************************/
00023 
00024 #include "LSM9DS1.h"
00025 #include "LSM9DS1_Registers.h"
00026 #include "LSM9DS1_Types.h"
00027 
00028 #define LSM9DS1_COMMUNICATION_TIMEOUT 1000
00029 
00030 float magSensitivity[4] = {0.00014, 0.00029, 0.00043, 0.00058};
00031 extern Serial pc;
00032 int16_t magn_ellipsoid_center[3] = {-425, 655, 204};
00033 float RM[3][3] = {{0.980752, -0.0124288, 0.00453175}, {-0.0124288, 0.977401, 0.0483545}, {0.00453175, 0.0483545, 0.857327}};
00034 
00035 
00036 
00037 LSM9DS1::LSM9DS1(SPI* _spi, DigitalOut* csM_, DigitalOut* csAG_) : spi(_spi)
00038 {
00039   //  spi = _spi;
00040     _mAddress = csM_;
00041     _xgAddress = csAG_;
00042 
00043     init(IMU_MODE_SPI, 0, 0); // dont know about 0xD6 or 0x3B
00044 }
00045 
00046 
00047 /*
00048 LSM9DS1::LSM9DS1()
00049 {
00050     //init(IMU_MODE_I2C, LSM9DS1_AG_ADDR(1), LSM9DS1_M_ADDR(1));
00051 }*/
00052 
00053 /*
00054 LSM9DS1::LSM9DS1(interface_mode interface, uint8_t xgAddr, uint8_t mAddr)
00055 {
00056     init(interface, xgAddr, mAddr);
00057 }
00058 */
00059 
00060 void LSM9DS1::init(interface_mode interface, uint8_t xgAddr, uint8_t mAddr)
00061 {
00062     settings.device.commInterface = interface;
00063     settings.device.agAddress = xgAddr;
00064     settings.device.mAddress = mAddr;
00065 
00066     settings.gyro.enabled = true;
00067     settings.gyro.enableX = true;
00068     settings.gyro.enableY = true;
00069     settings.gyro.enableZ = true;
00070     // gyro scale can be 245, 500, or 2000
00071     settings.gyro.scale = 500;
00072     // gyro sample rate: value between 1-6
00073     // 1 = 14.9    4 = 238
00074     // 2 = 59.5    5 = 476
00075     // 3 = 119     6 = 952
00076     settings.gyro.sampleRate = 6;
00077     // gyro cutoff frequency: value between 0-3
00078     // Actual value of cutoff frequency depends
00079     // on sample rate.
00080     settings.gyro.bandwidth = 0;
00081     settings.gyro.lowPowerEnable = false;
00082     settings.gyro.HPFEnable = false;
00083     // Gyro HPF cutoff frequency: value between 0-9
00084     // Actual value depends on sample rate. Only applies
00085     // if gyroHPFEnable is true.
00086     settings.gyro.HPFCutoff = 0;
00087     settings.gyro.flipX = false;
00088     settings.gyro.flipY = false;
00089     settings.gyro.flipZ = false;
00090     settings.gyro.orientation = 0;
00091     settings.gyro.latchInterrupt = true;
00092 
00093     settings.accel.enabled = true;
00094     settings.accel.enableX = true;
00095     settings.accel.enableY = true;
00096     settings.accel.enableZ = true;
00097     // accel scale can be 2, 4, 8, or 16
00098     settings.accel.scale = 2;
00099     // accel sample rate can be 1-6
00100     // 1 = 10 Hz    4 = 238 Hz
00101     // 2 = 50 Hz    5 = 476 Hz
00102     // 3 = 119 Hz   6 = 952 Hz
00103     settings.accel.sampleRate = 6;
00104     // Accel cutoff freqeuncy can be any value between -1 - 3.
00105     // -1 = bandwidth determined by sample rate
00106     // 0 = 408 Hz   2 = 105 Hz
00107     // 1 = 211 Hz   3 = 50 Hz
00108     settings.accel.bandwidth = -1;
00109     settings.accel.highResEnable = false;
00110     // accelHighResBandwidth can be any value between 0-3
00111     // LP cutoff is set to a factor of sample rate
00112     // 0 = ODR/50    2 = ODR/9
00113     // 1 = ODR/100   3 = ODR/400
00114     settings.accel.highResBandwidth = 0;
00115 
00116     settings.mag.enabled = true;
00117     // mag scale can be 4, 8, 12, or 16
00118     settings.mag.scale = 4;
00119     // mag data rate can be 0-7
00120     // 0 = 0.625 Hz  4 = 10 Hz
00121     // 1 = 1.25 Hz   5 = 20 Hz
00122     // 2 = 2.5 Hz    6 = 40 Hz
00123     // 3 = 5 Hz      7 = 80 Hz
00124     settings.mag.sampleRate = 7;
00125     settings.mag.tempCompensationEnable = false;
00126     // magPerformance can be any value between 0-3
00127     // 0 = Low power mode      2 = high performance
00128     // 1 = medium performance  3 = ultra-high performance
00129     settings.mag.XYPerformance = 3;
00130     settings.mag.ZPerformance = 3;
00131     settings.mag.lowPowerEnable = false;
00132     // magOperatingMode can be 0-2
00133     // 0 = continuous conversion
00134     // 1 = single-conversion
00135     // 2 = power down
00136     settings.mag.operatingMode = 0;
00137 
00138     settings.temp.enabled = true;
00139     for (int i=0; i<3; i++) {
00140         gBias[i] = 0;
00141         aBias[i] = 0;
00142         mBias[i] = 0;
00143         gBiasRaw[i] = 0;
00144         aBiasRaw[i] = 0;
00145         mBiasRaw[i] = 0;
00146     }
00147     _autoCalc = false;
00148 }
00149 
00150 
00151 uint16_t LSM9DS1::begin()
00152 {
00153     //! Todo: don't use _xgAddress or _mAddress, duplicating memory
00154     //_xgAddress = settings.device.agAddress;
00155    // _mAddress = settings.device.mAddress;
00156 
00157     constrainScales();
00158     // Once we have the scale values, we can calculate the resolution
00159     // of each sensor. That's what these functions are for. One for each sensor
00160     calcgRes(); // Calculate DPS / ADC tick, stored in gRes variable
00161     calcmRes(); // Calculate Gs / ADC tick, stored in mRes variable
00162     calcaRes(); // Calculate g / ADC tick, stored in aRes variable
00163 
00164     // Now, initialize our hardware interface.
00165     if (settings.device.commInterface == IMU_MODE_I2C)  // If we're using I2C
00166         initI2C();  // Initialize I2C
00167     else if (settings.device.commInterface == IMU_MODE_SPI)     // else, if we're using SPI
00168         initSPI();  // Initialize SPI
00169 
00170     // To verify communication, we can read from the WHO_AM_I register of
00171     // each device. Store those in a variable so we can return them.
00172     uint8_t mTest = mReadByte(WHO_AM_I_M);      // Read the gyro WHO_AM_I
00173     uint8_t xgTest = xgReadByte(WHO_AM_I_XG);   // Read the accel/mag WHO_AM_I
00174     pc.printf("%x, %x, %x, %x\n\r", mTest, xgTest, _xgAddress, _mAddress);
00175     uint16_t whoAmICombined = (xgTest << 8) | mTest;
00176 
00177     if (whoAmICombined != ((WHO_AM_I_AG_RSP << 8) | WHO_AM_I_M_RSP))
00178         return 0;
00179 
00180     // Gyro initialization stuff:
00181     initGyro(); // This will "turn on" the gyro. Setting up interrupts, etc.
00182 
00183     // Accelerometer initialization stuff:
00184     initAccel(); // "Turn on" all axes of the accel. Set up interrupts, etc.
00185 
00186     // Magnetometer initialization stuff:
00187     initMag(); // "Turn on" all axes of the mag. Set up interrupts, etc.
00188 
00189     // Once everything is initialized, return the WHO_AM_I registers we read:
00190     return whoAmICombined;
00191 }
00192 
00193 void LSM9DS1::initGyro()
00194 {
00195     uint8_t tempRegValue = 0;
00196 
00197     // CTRL_REG1_G (Default value: 0x00)
00198     // [ODR_G2][ODR_G1][ODR_G0][FS_G1][FS_G0][0][BW_G1][BW_G0]
00199     // ODR_G[2:0] - Output data rate selection
00200     // FS_G[1:0] - Gyroscope full-scale selection
00201     // BW_G[1:0] - Gyroscope bandwidth selection
00202 
00203     // To disable gyro, set sample rate bits to 0. We'll only set sample
00204     // rate if the gyro is enabled.
00205     if (settings.gyro.enabled) {
00206         tempRegValue = (settings.gyro.sampleRate & 0x07) << 5;
00207     }
00208     switch (settings.gyro.scale) {
00209         case 500:
00210             tempRegValue |= (0x1 << 3);
00211             break;
00212         case 2000:
00213             tempRegValue |= (0x3 << 3);
00214             break;
00215             // Otherwise we'll set it to 245 dps (0x0 << 4)
00216     }
00217     tempRegValue |= (settings.gyro.bandwidth & 0x3);
00218     xgWriteByte(CTRL_REG1_G, tempRegValue);
00219 
00220     // CTRL_REG2_G (Default value: 0x00)
00221     // [0][0][0][0][INT_SEL1][INT_SEL0][OUT_SEL1][OUT_SEL0]
00222     // INT_SEL[1:0] - INT selection configuration
00223     // OUT_SEL[1:0] - Out selection configuration
00224     xgWriteByte(CTRL_REG2_G, 0x00);
00225 
00226     // CTRL_REG3_G (Default value: 0x00)
00227     // [LP_mode][HP_EN][0][0][HPCF3_G][HPCF2_G][HPCF1_G][HPCF0_G]
00228     // LP_mode - Low-power mode enable (0: disabled, 1: enabled)
00229     // HP_EN - HPF enable (0:disabled, 1: enabled)
00230     // HPCF_G[3:0] - HPF cutoff frequency
00231     tempRegValue = settings.gyro.lowPowerEnable ? (1<<7) : 0;
00232     if (settings.gyro.HPFEnable) {
00233         tempRegValue |= (1<<6) | (settings.gyro.HPFCutoff & 0x0F);
00234     }
00235     xgWriteByte(CTRL_REG3_G, tempRegValue);
00236 
00237     // CTRL_REG4 (Default value: 0x38)
00238     // [0][0][Zen_G][Yen_G][Xen_G][0][LIR_XL1][4D_XL1]
00239     // Zen_G - Z-axis output enable (0:disable, 1:enable)
00240     // Yen_G - Y-axis output enable (0:disable, 1:enable)
00241     // Xen_G - X-axis output enable (0:disable, 1:enable)
00242     // LIR_XL1 - Latched interrupt (0:not latched, 1:latched)
00243     // 4D_XL1 - 4D option on interrupt (0:6D used, 1:4D used)
00244     tempRegValue = 0;
00245     if (settings.gyro.enableZ) tempRegValue |= (1<<5);
00246     if (settings.gyro.enableY) tempRegValue |= (1<<4);
00247     if (settings.gyro.enableX) tempRegValue |= (1<<3);
00248     if (settings.gyro.latchInterrupt) tempRegValue |= (1<<1);
00249     xgWriteByte(CTRL_REG4, tempRegValue);
00250 
00251     // ORIENT_CFG_G (Default value: 0x00)
00252     // [0][0][SignX_G][SignY_G][SignZ_G][Orient_2][Orient_1][Orient_0]
00253     // SignX_G - Pitch axis (X) angular rate sign (0: positive, 1: negative)
00254     // Orient [2:0] - Directional user orientation selection
00255     tempRegValue = 0;
00256     if (settings.gyro.flipX) tempRegValue |= (1<<5);
00257     if (settings.gyro.flipY) tempRegValue |= (1<<4);
00258     if (settings.gyro.flipZ) tempRegValue |= (1<<3);
00259     xgWriteByte(ORIENT_CFG_G, tempRegValue);
00260 }
00261 
00262 void LSM9DS1::initAccel()
00263 {
00264     uint8_t tempRegValue = 0;
00265 
00266     //  CTRL_REG5_XL (0x1F) (Default value: 0x38)
00267     //  [DEC_1][DEC_0][Zen_XL][Yen_XL][Zen_XL][0][0][0]
00268     //  DEC[0:1] - Decimation of accel data on OUT REG and FIFO.
00269     //      00: None, 01: 2 samples, 10: 4 samples 11: 8 samples
00270     //  Zen_XL - Z-axis output enabled
00271     //  Yen_XL - Y-axis output enabled
00272     //  Xen_XL - X-axis output enabled
00273     if (settings.accel.enableZ) tempRegValue |= (1<<5);
00274     if (settings.accel.enableY) tempRegValue |= (1<<4);
00275     if (settings.accel.enableX) tempRegValue |= (1<<3);
00276 
00277     xgWriteByte(CTRL_REG5_XL, tempRegValue);
00278 
00279     // CTRL_REG6_XL (0x20) (Default value: 0x00)
00280     // [ODR_XL2][ODR_XL1][ODR_XL0][FS1_XL][FS0_XL][BW_SCAL_ODR][BW_XL1][BW_XL0]
00281     // ODR_XL[2:0] - Output data rate & power mode selection
00282     // FS_XL[1:0] - Full-scale selection
00283     // BW_SCAL_ODR - Bandwidth selection
00284     // BW_XL[1:0] - Anti-aliasing filter bandwidth selection
00285     tempRegValue = 0;
00286     // To disable the accel, set the sampleRate bits to 0.
00287     if (settings.accel.enabled) {
00288         tempRegValue |= (settings.accel.sampleRate & 0x07) << 5;
00289     }
00290     switch (settings.accel.scale) {
00291         case 4:
00292             tempRegValue |= (0x2 << 3);
00293             break;
00294         case 8:
00295             tempRegValue |= (0x3 << 3);
00296             break;
00297         case 16:
00298             tempRegValue |= (0x1 << 3);
00299             break;
00300             // Otherwise it'll be set to 2g (0x0 << 3)
00301     }
00302     if (settings.accel.bandwidth >= 0) {
00303         tempRegValue |= (1<<2); // Set BW_SCAL_ODR
00304         tempRegValue |= (settings.accel.bandwidth & 0x03);
00305     }
00306     xgWriteByte(CTRL_REG6_XL, tempRegValue);
00307 
00308     // CTRL_REG7_XL (0x21) (Default value: 0x00)
00309     // [HR][DCF1][DCF0][0][0][FDS][0][HPIS1]
00310     // HR - High resolution mode (0: disable, 1: enable)
00311     // DCF[1:0] - Digital filter cutoff frequency
00312     // FDS - Filtered data selection
00313     // HPIS1 - HPF enabled for interrupt function
00314     tempRegValue = 0;
00315     if (settings.accel.highResEnable) {
00316         tempRegValue |= (1<<7); // Set HR bit
00317         tempRegValue |= (settings.accel.highResBandwidth & 0x3) << 5;
00318     }
00319     xgWriteByte(CTRL_REG7_XL, tempRegValue);
00320 }
00321 
00322 // This is a function that uses the FIFO to accumulate sample of accelerometer and gyro data, average
00323 // them, scales them to  gs and deg/s, respectively, and then passes the biases to the main sketch
00324 // for subtraction from all subsequent data. There are no gyro and accelerometer bias registers to store
00325 // the data as there are in the ADXL345, a precursor to the LSM9DS0, or the MPU-9150, so we have to
00326 // subtract the biases ourselves. This results in a more accurate measurement in general and can
00327 // remove errors due to imprecise or varying initial placement. Calibration of sensor data in this manner
00328 // is good practice.
00329 void LSM9DS1::calibrate(bool autoCalc)
00330 {
00331     uint8_t data[6] = {0, 0, 0, 0, 0, 0};
00332     uint8_t samples = 0;
00333     int ii;
00334     int32_t aBiasRawTemp[3] = {0, 0, 0};
00335     int32_t gBiasRawTemp[3] = {0, 0, 0};
00336 
00337     // Turn on FIFO and set threshold to 32 samples
00338     enableFIFO(true);
00339     setFIFO(FIFO_THS, 0x1F);
00340     while (samples < 0x1F) {
00341         samples = (xgReadByte(FIFO_SRC) & 0x3F); // Read number of stored samples
00342     }
00343     for(ii = 0; ii < samples ; ii++) {
00344         // Read the gyro data stored in the FIFO
00345         readGyro();
00346         gBiasRawTemp[0] += gx;
00347         gBiasRawTemp[1] += gy;
00348         gBiasRawTemp[2] += gz;
00349         readAccel();
00350         aBiasRawTemp[0] += ax;
00351         aBiasRawTemp[1] += ay;
00352         aBiasRawTemp[2] += az - (int16_t)(1./aRes); // Assumes sensor facing up!
00353     }
00354     for (ii = 0; ii < 3; ii++) {
00355         gBiasRaw[ii] = gBiasRawTemp[ii] / samples;
00356         gBias[ii] = calcGyro(gBiasRaw[ii]);
00357         aBiasRaw[ii] = aBiasRawTemp[ii] / samples;
00358         aBias[ii] = calcAccel(aBiasRaw[ii]);
00359     }
00360 
00361     enableFIFO(false);
00362     setFIFO(FIFO_OFF, 0x00);
00363 
00364     if (autoCalc) _autoCalc = true;
00365 }
00366 
00367 void LSM9DS1::calibrateMag(bool loadIn)
00368 {
00369     int i, j;
00370     int16_t magMin[3] = {0, 0, 0};
00371     int16_t magMax[3] = {0, 0, 0}; // The road warrior
00372 
00373     for (i=0; i<128; i++) {
00374         while (!magAvailable())
00375             ;
00376         readMag();
00377         int16_t magTemp[3] = {0, 0, 0};
00378         magTemp[0] = mx;
00379         magTemp[1] = my;
00380         magTemp[2] = mz;
00381         for (j = 0; j < 3; j++) {
00382             if (magTemp[j] > magMax[j]) magMax[j] = magTemp[j];
00383             if (magTemp[j] < magMin[j]) magMin[j] = magTemp[j];
00384         }
00385     }
00386     for (j = 0; j < 3; j++) {
00387         mBiasRaw[j] = (magMax[j] + magMin[j]) / 2;
00388         mBias[j] = calcMag(mBiasRaw[j]);
00389         if (loadIn)
00390             magOffset(j, mBiasRaw[j]);
00391     }
00392 
00393 }
00394 void LSM9DS1::magOffset(uint8_t axis, int16_t offset)
00395 {
00396     if (axis > 2)
00397         return;
00398     uint8_t msb, lsb;
00399     msb = (offset & 0xFF00) >> 8;
00400     lsb = offset & 0x00FF;
00401     mWriteByte(OFFSET_X_REG_L_M + (2 * axis), lsb);
00402     mWriteByte(OFFSET_X_REG_H_M + (2 * axis), msb);
00403 }
00404 
00405 void LSM9DS1::initMag()
00406 {
00407     uint8_t tempRegValue = 0;
00408 
00409     // CTRL_REG1_M (Default value: 0x10)
00410     // [TEMP_COMP][OM1][OM0][DO2][DO1][DO0][0][ST]
00411     // TEMP_COMP - Temperature compensation
00412     // OM[1:0] - X & Y axes op mode selection
00413     //  00:low-power, 01:medium performance
00414     //  10: high performance, 11:ultra-high performance
00415     // DO[2:0] - Output data rate selection
00416     // ST - Self-test enable
00417     if (settings.mag.tempCompensationEnable) tempRegValue |= (1<<7);
00418     tempRegValue |= (settings.mag.XYPerformance & 0x3) << 5;
00419     tempRegValue |= (settings.mag.sampleRate & 0x7) << 2;
00420     mWriteByte(CTRL_REG1_M, tempRegValue);
00421 
00422     // CTRL_REG2_M (Default value 0x00)
00423     // [0][FS1][FS0][0][REBOOT][SOFT_RST][0][0]
00424     // FS[1:0] - Full-scale configuration
00425     // REBOOT - Reboot memory content (0:normal, 1:reboot)
00426     // SOFT_RST - Reset config and user registers (0:default, 1:reset)
00427     tempRegValue = 0;
00428     switch (settings.mag.scale) {
00429         case 8:
00430             tempRegValue |= (0x1 << 5);
00431             break;
00432         case 12:
00433             tempRegValue |= (0x2 << 5);
00434             break;
00435         case 16:
00436             tempRegValue |= (0x3 << 5);
00437             break;
00438             // Otherwise we'll default to 4 gauss (00)
00439     }
00440     mWriteByte(CTRL_REG2_M, tempRegValue); // +/-4Gauss
00441 
00442     // CTRL_REG3_M (Default value: 0x03)
00443     // [I2C_DISABLE][0][LP][0][0][SIM][MD1][MD0]
00444     // I2C_DISABLE - Disable I2C interace (0:enable, 1:disable)
00445     // LP - Low-power mode cofiguration (1:enable)
00446     // SIM - SPI mode selection (0:write-only, 1:read/write enable)
00447     // MD[1:0] - Operating mode
00448     //  00:continuous conversion, 01:single-conversion,
00449     //  10,11: Power-down
00450     tempRegValue = 0;
00451     if (settings.mag.lowPowerEnable) tempRegValue |= (1<<5);
00452     tempRegValue |= (settings.mag.operatingMode & 0x3);
00453     mWriteByte(CTRL_REG3_M, tempRegValue); // Continuous conversion mode
00454 
00455     // CTRL_REG4_M (Default value: 0x00)
00456     // [0][0][0][0][OMZ1][OMZ0][BLE][0]
00457     // OMZ[1:0] - Z-axis operative mode selection
00458     //  00:low-power mode, 01:medium performance
00459     //  10:high performance, 10:ultra-high performance
00460     // BLE - Big/little endian data
00461     tempRegValue = 0;
00462     tempRegValue = (settings.mag.ZPerformance & 0x3) << 2;
00463     mWriteByte(CTRL_REG4_M, tempRegValue);
00464 
00465     // CTRL_REG5_M (Default value: 0x00)
00466     // [0][BDU][0][0][0][0][0][0]
00467     // BDU - Block data update for magnetic data
00468     //  0:continuous, 1:not updated until MSB/LSB are read
00469     tempRegValue = 0;
00470     mWriteByte(CTRL_REG5_M, tempRegValue);
00471 }
00472 
00473 uint8_t LSM9DS1::accelAvailable()
00474 {
00475     uint8_t status = xgReadByte(STATUS_REG_1);
00476 
00477     return (status & (1<<0));
00478 }
00479 
00480 uint8_t LSM9DS1::gyroAvailable()
00481 {
00482     uint8_t status = xgReadByte(STATUS_REG_1);
00483 
00484     return ((status & (1<<1)) >> 1);
00485 }
00486 
00487 uint8_t LSM9DS1::tempAvailable()
00488 {
00489     uint8_t status = xgReadByte(STATUS_REG_1);
00490 
00491     return ((status & (1<<2)) >> 2);
00492 }
00493 
00494 uint8_t LSM9DS1::magAvailable(lsm9ds1_axis axis)
00495 {
00496     uint8_t status;
00497     status = mReadByte(STATUS_REG_M);
00498 
00499     return ((status & (1<<axis)) >> axis);
00500 }
00501 
00502 void LSM9DS1::readAccel()
00503 {
00504     uint8_t temp[6]; // We'll read six bytes from the accelerometer into temp
00505     xgReadBytes(OUT_X_L_XL, temp, 6); // Read 6 bytes, beginning at OUT_X_L_XL
00506     ax = (temp[1] << 8) | temp[0]; // Store x-axis values into ax
00507     ay = (temp[3] << 8) | temp[2]; // Store y-axis values into ay
00508     az = (temp[5] << 8) | temp[4]; // Store z-axis values into az
00509     if (_autoCalc) {
00510         ax -= aBiasRaw[X_AXIS];
00511         ay -= aBiasRaw[Y_AXIS];
00512         az -= aBiasRaw[Z_AXIS];
00513     }
00514 }
00515 
00516 int16_t LSM9DS1::readAccel(lsm9ds1_axis axis)
00517 {
00518     uint8_t temp[2];
00519     int16_t value;
00520     xgReadBytes(OUT_X_L_XL + (2 * axis), temp, 2);
00521     value = (temp[1] << 8) | temp[0];
00522 
00523     if (_autoCalc)
00524         value -= aBiasRaw[axis];
00525 
00526     return value;
00527 }
00528 
00529 void LSM9DS1::readMag()
00530 {
00531     uint8_t temp[6]; // We'll read six bytes from the mag into temp
00532     mReadBytes(OUT_X_L_M, temp, 6); // Read 6 bytes, beginning at OUT_X_L_M
00533     mx = (temp[1] << 8) | temp[0]; // Store x-axis values into mx
00534     my = (temp[3] << 8) | temp[2]; // Store y-axis values into my
00535     mz = (temp[5] << 8) | temp[4]; // Store z-axis values into mz
00536 }
00537 void LSM9DS1::readMag_calibrated()
00538 {
00539     uint8_t temp[6]; // We'll read six bytes from the mag into temp
00540     mReadBytes(OUT_X_L_M, temp, 6); // Read 6 bytes, beginning at OUT_X_L_M
00541     mx = (temp[1] << 8) | temp[0]; // Store x-axis values into mx
00542     my = (temp[3] << 8) | temp[2]; // Store y-axis values into my
00543     mz = (temp[5] << 8) | temp[4]; // Store z-axis values into mz
00544     mx -=magn_ellipsoid_center[0];
00545     my -=magn_ellipsoid_center[1];
00546     mz -=magn_ellipsoid_center[2];
00547     float dum[3];
00548     for(int i=0;i<3;i++)
00549         dum[i] = RM[i][0] * (float)mx + RM[i][1] * (float)my + RM[i][2] * (float)mz;
00550     mx=(int16_t)dum[0];
00551     my=(int16_t)dum[1];
00552     mz=(int16_t)dum[2];
00553     
00554 }
00555 
00556 int16_t LSM9DS1::readMag(lsm9ds1_axis axis)
00557 {
00558     uint8_t temp[2];
00559     mReadBytes(OUT_X_L_M + (2 * axis), temp, 2);
00560     return (temp[1] << 8) | temp[0];
00561 }
00562 
00563 void LSM9DS1::readTemp()
00564 {
00565     uint8_t temp[2]; // We'll read two bytes from the temperature sensor into temp
00566     xgReadBytes(OUT_TEMP_L, temp, 2); // Read 2 bytes, beginning at OUT_TEMP_L
00567     temperature = ((int16_t)temp[1] << 8) | temp[0];
00568 }
00569 
00570 void LSM9DS1::readGyro()
00571 {
00572     uint8_t temp[6]; // We'll read six bytes from the gyro into temp
00573     xgReadBytes(OUT_X_L_G, temp, 6); // Read 6 bytes, beginning at OUT_X_L_G
00574     gx = (temp[1] << 8) | temp[0]; // Store x-axis values into gx
00575     gy = (temp[3] << 8) | temp[2]; // Store y-axis values into gy
00576     gz = (temp[5] << 8) | temp[4]; // Store z-axis values into gz
00577     if (_autoCalc) {
00578         gx -= gBiasRaw[X_AXIS];
00579         gy -= gBiasRaw[Y_AXIS];
00580         gz -= gBiasRaw[Z_AXIS];
00581     }
00582 }
00583 
00584 int16_t LSM9DS1::readGyro(lsm9ds1_axis axis)
00585 {
00586     uint8_t temp[2];
00587     int16_t value;
00588 
00589     xgReadBytes(OUT_X_L_G + (2 * axis), temp, 2);
00590 
00591     value = (temp[1] << 8) | temp[0];
00592 
00593     if (_autoCalc)
00594         value -= gBiasRaw[axis];
00595 
00596     return value;
00597 }
00598 
00599 float LSM9DS1::calcGyro(int16_t gyro)
00600 {
00601     // Return the gyro raw reading times our pre-calculated DPS / (ADC tick):
00602     return gRes * gyro;
00603 }
00604 
00605 float LSM9DS1::calcAccel(int16_t accel)
00606 {
00607     // Return the accel raw reading times our pre-calculated g's / (ADC tick):
00608     return aRes * accel;
00609 }
00610 
00611 float LSM9DS1::calcMag(int16_t mag)
00612 {
00613     // Return the mag raw reading times our pre-calculated Gs / (ADC tick):
00614     return mRes * mag;
00615 }
00616 
00617 void LSM9DS1::setGyroScale(uint16_t gScl)
00618 {
00619     // Read current value of CTRL_REG1_G:
00620     uint8_t ctrl1RegValue = xgReadByte(CTRL_REG1_G);
00621     // Mask out scale bits (3 & 4):
00622     ctrl1RegValue &= 0xE7;
00623     switch (gScl) {
00624         case 500:
00625             ctrl1RegValue |= (0x1 << 3);
00626             settings.gyro.scale = 500;
00627             break;
00628         case 2000:
00629             ctrl1RegValue |= (0x3 << 3);
00630             settings.gyro.scale = 2000;
00631             break;
00632         default: // Otherwise we'll set it to 245 dps (0x0 << 4)
00633             settings.gyro.scale = 245;
00634             break;
00635     }
00636     xgWriteByte(CTRL_REG1_G, ctrl1RegValue);
00637 
00638     calcgRes();
00639 }
00640 
00641 void LSM9DS1::setAccelScale(uint8_t aScl)
00642 {
00643     // We need to preserve the other bytes in CTRL_REG6_XL. So, first read it:
00644     uint8_t tempRegValue = xgReadByte(CTRL_REG6_XL);
00645     // Mask out accel scale bits:
00646     tempRegValue &= 0xE7;
00647 
00648     switch (aScl) {
00649         case 4:
00650             tempRegValue |= (0x2 << 3);
00651             settings.accel.scale = 4;
00652             break;
00653         case 8:
00654             tempRegValue |= (0x3 << 3);
00655             settings.accel.scale = 8;
00656             break;
00657         case 16:
00658             tempRegValue |= (0x1 << 3);
00659             settings.accel.scale = 16;
00660             break;
00661         default: // Otherwise it'll be set to 2g (0x0 << 3)
00662             settings.accel.scale = 2;
00663             break;
00664     }
00665     xgWriteByte(CTRL_REG6_XL, tempRegValue);
00666 
00667     // Then calculate a new aRes, which relies on aScale being set correctly:
00668     calcaRes();
00669 }
00670 
00671 void LSM9DS1::setMagScale(uint8_t mScl)
00672 {
00673     // We need to preserve the other bytes in CTRL_REG6_XM. So, first read it:
00674     uint8_t temp = mReadByte(CTRL_REG2_M);
00675     // Then mask out the mag scale bits:
00676     temp &= 0xFF^(0x3 << 5);
00677 
00678     switch (mScl) {
00679         case 8:
00680             temp |= (0x1 << 5);
00681             settings.mag.scale = 8;
00682             break;
00683         case 12:
00684             temp |= (0x2 << 5);
00685             settings.mag.scale = 12;
00686             break;
00687         case 16:
00688             temp |= (0x3 << 5);
00689             settings.mag.scale = 16;
00690             break;
00691         default: // Otherwise we'll default to 4 gauss (00)
00692             settings.mag.scale = 4;
00693             break;
00694     }
00695 
00696     // And write the new register value back into CTRL_REG6_XM:
00697     mWriteByte(CTRL_REG2_M, temp);
00698 
00699     // We've updated the sensor, but we also need to update our class variables
00700     // First update mScale:
00701     //mScale = mScl;
00702     // Then calculate a new mRes, which relies on mScale being set correctly:
00703     calcmRes();
00704 }
00705 
00706 void LSM9DS1::setGyroODR(uint8_t gRate)
00707 {
00708     // Only do this if gRate is not 0 (which would disable the gyro)
00709     if ((gRate & 0x07) != 0) {
00710         // We need to preserve the other bytes in CTRL_REG1_G. So, first read it:
00711         uint8_t temp = xgReadByte(CTRL_REG1_G);
00712         // Then mask out the gyro ODR bits:
00713         temp &= 0xFF^(0x7 << 5);
00714         temp |= (gRate & 0x07) << 5;
00715         // Update our settings struct
00716         settings.gyro.sampleRate = gRate & 0x07;
00717         // And write the new register value back into CTRL_REG1_G:
00718         xgWriteByte(CTRL_REG1_G, temp);
00719     }
00720 }
00721 
00722 void LSM9DS1::setAccelODR(uint8_t aRate)
00723 {
00724     // Only do this if aRate is not 0 (which would disable the accel)
00725     if ((aRate & 0x07) != 0) {
00726         // We need to preserve the other bytes in CTRL_REG1_XM. So, first read it:
00727         uint8_t temp = xgReadByte(CTRL_REG6_XL);
00728         // Then mask out the accel ODR bits:
00729         temp &= 0x1F;
00730         // Then shift in our new ODR bits:
00731         temp |= ((aRate & 0x07) << 5);
00732         settings.accel.sampleRate = aRate & 0x07;
00733         // And write the new register value back into CTRL_REG1_XM:
00734         xgWriteByte(CTRL_REG6_XL, temp);
00735     }
00736 }
00737 
00738 void LSM9DS1::setMagODR(uint8_t mRate)
00739 {
00740     // We need to preserve the other bytes in CTRL_REG5_XM. So, first read it:
00741     uint8_t temp = mReadByte(CTRL_REG1_M);
00742     // Then mask out the mag ODR bits:
00743     temp &= 0xFF^(0x7 << 2);
00744     // Then shift in our new ODR bits:
00745     temp |= ((mRate & 0x07) << 2);
00746     settings.mag.sampleRate = mRate & 0x07;
00747     // And write the new register value back into CTRL_REG5_XM:
00748     mWriteByte(CTRL_REG1_M, temp);
00749 }
00750 
00751 void LSM9DS1::calcgRes()
00752 {
00753     gRes = ((float) settings.gyro.scale) / 32768.0;
00754 }
00755 
00756 void LSM9DS1::calcaRes()
00757 {
00758     aRes = ((float) settings.accel.scale) / 32768.0;
00759 }
00760 
00761 void LSM9DS1::calcmRes()
00762 {
00763     //mRes = ((float) settings.mag.scale) / 32768.0;
00764     switch (settings.mag.scale) {
00765         case 4:
00766             mRes = magSensitivity[0];
00767             break;
00768         case 8:
00769             mRes = magSensitivity[1];
00770             break;
00771         case 12:
00772             mRes = magSensitivity[2];
00773             break;
00774         case 16:
00775             mRes = magSensitivity[3];
00776             break;
00777     }
00778 
00779 }
00780 /*
00781 void LSM9DS1::configInt(interrupt_select interrupt, uint8_t generator,
00782                         h_lactive activeLow, pp_od pushPull)
00783 {
00784     // Write to INT1_CTRL or INT2_CTRL. [interupt] should already be one of
00785     // those two values.
00786     // [generator] should be an OR'd list of values from the interrupt_generators enum
00787     xgWriteByte(interrupt, generator);
00788 
00789     // Configure CTRL_REG8
00790     uint8_t temp;
00791     temp = xgReadByte(CTRL_REG8);
00792 
00793     if (activeLow) temp |= (1<<5);
00794     else temp &= ~(1<<5);
00795 
00796     if (pushPull) temp &= ~(1<<4);
00797     else temp |= (1<<4);
00798 
00799     xgWriteByte(CTRL_REG8, temp);
00800 }*/
00801 
00802 void LSM9DS1::configInactivity(uint8_t duration, uint8_t threshold, bool sleepOn)
00803 {
00804     uint8_t temp = 0;
00805 
00806     temp = threshold & 0x7F;
00807     if (sleepOn) temp |= (1<<7);
00808     xgWriteByte(ACT_THS, temp);
00809 
00810     xgWriteByte(ACT_DUR, duration);
00811 }
00812 
00813 /*
00814 uint8_t LSM9DS1::getInactivity()
00815 {
00816     uint8_t temp = xgReadByte(STATUS_REG_0);
00817     temp &= (0x10);
00818     return temp;
00819 }
00820 
00821 void LSM9DS1::configAccelInt(uint8_t generator, bool andInterrupts)
00822 {
00823     // Use variables from accel_interrupt_generator, OR'd together to create
00824     // the [generator]value.
00825     uint8_t temp = generator;
00826     if (andInterrupts) temp |= 0x80;
00827     xgWriteByte(INT_GEN_CFG_XL, temp);
00828 }
00829 
00830 void LSM9DS1::configAccelThs(uint8_t threshold, lsm9ds1_axis axis, uint8_t duration, bool wait)
00831 {
00832     // Write threshold value to INT_GEN_THS_?_XL.
00833     // axis will be 0, 1, or 2 (x, y, z respectively)
00834     xgWriteByte(INT_GEN_THS_X_XL + axis, threshold);
00835 
00836     // Write duration and wait to INT_GEN_DUR_XL
00837     uint8_t temp;
00838     temp = (duration & 0x7F);
00839     if (wait) temp |= 0x80;
00840     xgWriteByte(INT_GEN_DUR_XL, temp);
00841 }
00842 
00843 uint8_t LSM9DS1::getAccelIntSrc()
00844 {
00845     uint8_t intSrc = xgReadByte(INT_GEN_SRC_XL);
00846 
00847     // Check if the IA_XL (interrupt active) bit is set
00848     if (intSrc & (1<<6)) {
00849         return (intSrc & 0x3F);
00850     }
00851 
00852     return 0;
00853 }
00854 
00855 void LSM9DS1::configGyroInt(uint8_t generator, bool aoi, bool latch)
00856 {
00857     // Use variables from accel_interrupt_generator, OR'd together to create
00858     // the [generator]value.
00859     uint8_t temp = generator;
00860     if (aoi) temp |= 0x80;
00861     if (latch) temp |= 0x40;
00862     xgWriteByte(INT_GEN_CFG_G, temp);
00863 }
00864 
00865 void LSM9DS1::configGyroThs(int16_t threshold, lsm9ds1_axis axis, uint8_t duration, bool wait)
00866 {
00867     uint8_t buffer[2];
00868     buffer[0] = (threshold & 0x7F00) >> 8;
00869     buffer[1] = (threshold & 0x00FF);
00870     // Write threshold value to INT_GEN_THS_?H_G and  INT_GEN_THS_?L_G.
00871     // axis will be 0, 1, or 2 (x, y, z respectively)
00872     xgWriteByte(INT_GEN_THS_XH_G + (axis * 2), buffer[0]);
00873     xgWriteByte(INT_GEN_THS_XH_G + 1 + (axis * 2), buffer[1]);
00874 
00875     // Write duration and wait to INT_GEN_DUR_XL
00876     uint8_t temp;
00877     temp = (duration & 0x7F);
00878     if (wait) temp |= 0x80;
00879     xgWriteByte(INT_GEN_DUR_G, temp);
00880 }
00881 
00882 uint8_t LSM9DS1::getGyroIntSrc()
00883 {
00884     uint8_t intSrc = xgReadByte(INT_GEN_SRC_G);
00885 
00886     // Check if the IA_G (interrupt active) bit is set
00887     if (intSrc & (1<<6)) {
00888         return (intSrc & 0x3F);
00889     }
00890 
00891     return 0;
00892 }
00893 
00894 
00895 void LSM9DS1::configMagInt(uint8_t generator, h_lactive activeLow, bool latch)
00896 {
00897     // Mask out non-generator bits (0-4)
00898     uint8_t config = (generator & 0xE0);
00899     // IEA bit is 0 for active-low, 1 for active-high.
00900     if (activeLow == INT_ACTIVE_HIGH) config |= (1<<2);
00901     // IEL bit is 0 for latched, 1 for not-latched
00902     if (!latch) config |= (1<<1);
00903     // As long as we have at least 1 generator, enable the interrupt
00904     if (generator != 0) config |= (1<<0);
00905 
00906     mWriteByte(INT_CFG_M, config);
00907 }
00908 
00909 
00910 uint8_t LSM9DS1::getMagIntSrc()
00911 {
00912     uint8_t intSrc = mReadByte(INT_SRC_M);
00913 
00914     // Check if the INT (interrupt active) bit is set
00915     if (intSrc & (1<<0)) {
00916         return (intSrc & 0xFE);
00917     }
00918 
00919     return 0;
00920 }*/
00921 
00922 void LSM9DS1::configMagThs(uint16_t threshold)
00923 {
00924     // Write high eight bits of [threshold] to INT_THS_H_M
00925     mWriteByte(INT_THS_H_M, uint8_t((threshold & 0x7F00) >> 8));
00926     // Write low eight bits of [threshold] to INT_THS_L_M
00927     mWriteByte(INT_THS_L_M, uint8_t(threshold & 0x00FF));
00928 }
00929 
00930 void LSM9DS1::sleepGyro(bool enable)
00931 {
00932     uint8_t temp = xgReadByte(CTRL_REG9);
00933     if (enable) temp |= (1<<6);
00934     else temp &= ~(1<<6);
00935     xgWriteByte(CTRL_REG9, temp);
00936 }
00937 
00938 void LSM9DS1::enableFIFO(bool enable)
00939 {
00940     uint8_t temp = xgReadByte(CTRL_REG9);
00941     if (enable) temp |= (1<<1);
00942     else temp &= ~(1<<1);
00943     xgWriteByte(CTRL_REG9, temp);
00944 }
00945 
00946 void LSM9DS1::setFIFO(fifoMode_type fifoMode, uint8_t fifoThs)
00947 {
00948     // Limit threshold - 0x1F (31) is the maximum. If more than that was asked
00949     // limit it to the maximum.
00950     uint8_t threshold = fifoThs <= 0x1F ? fifoThs : 0x1F;
00951     xgWriteByte(FIFO_CTRL, ((fifoMode & 0x7) << 5) | (threshold & 0x1F));
00952 }
00953 
00954 uint8_t LSM9DS1::getFIFOSamples()
00955 {
00956     return (xgReadByte(FIFO_SRC) & 0x3F);
00957 }
00958 
00959 void LSM9DS1::constrainScales()
00960 {
00961     if ((settings.gyro.scale != 245) && (settings.gyro.scale != 500) &&
00962             (settings.gyro.scale != 2000)) {
00963         settings.gyro.scale = 245;
00964     }
00965 
00966     if ((settings.accel.scale != 2) && (settings.accel.scale != 4) &&
00967             (settings.accel.scale != 8) && (settings.accel.scale != 16)) {
00968         settings.accel.scale = 2;
00969     }
00970 
00971     if ((settings.mag.scale != 4) && (settings.mag.scale != 8) &&
00972             (settings.mag.scale != 12) && (settings.mag.scale != 16)) {
00973         settings.mag.scale = 4;
00974     }
00975 }
00976 
00977 void LSM9DS1::xgWriteByte(uint8_t subAddress, uint8_t data)
00978 {
00979     // Whether we're using I2C or SPI, write a byte using the
00980     // gyro-specific I2C address or SPI CS pin.
00981     if (settings.device.commInterface == IMU_MODE_I2C) {
00982         printf("yo");
00983        // I2CwriteByte(_xgAddress, subAddress, data);
00984     } else if (settings.device.commInterface == IMU_MODE_SPI) {
00985         SPIwriteByte(_xgAddress, subAddress, data);
00986     }
00987 }
00988 
00989 
00990 
00991 void LSM9DS1::mWriteByte(uint8_t subAddress, uint8_t data)
00992 {
00993     // Whether we're using I2C or SPI, write a byte using the
00994     // accelerometer-specific I2C address or SPI CS pin.
00995    // if (settings.device.commInterface == IMU_MODE_I2C)
00996        // return I2CwriteByte(_mAddress, subAddress, data);
00997      if (settings.device.commInterface == IMU_MODE_SPI)
00998         return SPIwriteByte(_mAddress, subAddress, data);
00999 }
01000 
01001 uint8_t LSM9DS1::xgReadByte(uint8_t subAddress)
01002 {
01003     // Whether we're using I2C or SPI, read a byte using the
01004     // gyro-specific I2C address or SPI CS pin.
01005     //if (settings.device.commInterface == IMU_MODE_I2C)
01006        // return I2CreadByte(_xgAddress, subAddress);
01007      if (settings.device.commInterface == IMU_MODE_SPI)
01008         return SPIreadByte(_xgAddress, subAddress);
01009 }
01010 
01011 void LSM9DS1::xgReadBytes(uint8_t subAddress, uint8_t * dest, uint8_t count)
01012 {
01013     // Whether we're using I2C or SPI, read multiple bytes using the
01014     // gyro-specific I2C address or SPI CS pin.
01015     if (settings.device.commInterface == IMU_MODE_I2C) {
01016       //  I2CreadBytes(_xgAddress, subAddress, dest, count);
01017     } else if (settings.device.commInterface == IMU_MODE_SPI) {
01018         SPIreadBytes(_xgAddress, subAddress, dest, count);
01019     }
01020 }
01021 
01022 uint8_t LSM9DS1::mReadByte(uint8_t subAddress)
01023 {
01024     // Whether we're using I2C or SPI, read a byte using the
01025     // accelerometer-specific I2C address or SPI CS pin.
01026     //if (settings.device.commInterface == IMU_MODE_I2C)
01027      //   return I2CreadByte(_mAddress, subAddress);
01028      if (settings.device.commInterface == IMU_MODE_SPI)
01029         return SPIreadByte(_mAddress, subAddress);
01030 }
01031 
01032 void LSM9DS1::mReadBytes(uint8_t subAddress, uint8_t * dest, uint8_t count)
01033 {
01034     // Whether we're using I2C or SPI, read multiple bytes using the
01035     // accelerometer-specific I2C address or SPI CS pin.
01036    // if (settings.device.commInterface == IMU_MODE_I2C)
01037      //   I2CreadBytes(_mAddress, subAddress, dest, count);
01038      if (settings.device.commInterface == IMU_MODE_SPI)
01039         SPIreadBytes(_mAddress, subAddress, dest, count);
01040 }
01041 
01042 void LSM9DS1::initSPI()
01043 {
01044     spi->format(8, 0); //8, 3
01045     spi->frequency(1000000);
01046 
01047     *_xgAddress = 1;
01048     *_mAddress = 1;
01049 
01050     /*
01051     pinMode(_xgAddress, OUTPUT);
01052     digitalWrite(_xgAddress, HIGH);
01053     pinMode(_mAddress, OUTPUT);
01054     digitalWrite(_mAddress, HIGH);
01055 
01056     spi->begin();
01057     // Maximum SPI frequency is 10MHz, could divide by 2 here:
01058     spi->setClockDivider(SPI_CLOCK_DIV2);
01059     // Data is read and written MSb first.
01060     spi->setBitOrder(MSBFIRST);
01061     // Data is captured on rising edge of clock (CPHA = 0)
01062     // Base value of the clock is HIGH (CPOL = 1)
01063     spi->setDataMode(SPI_MODE0);
01064     */
01065 }
01066 
01067 void LSM9DS1::SPIwriteByte(DigitalOut* csPin, uint8_t subAddress, uint8_t data)
01068 {
01069     *csPin = 0;
01070     wait_us(1);
01071 
01072     spi->write(subAddress & 0x3F);
01073     spi->write(data & 0xFF);
01074 
01075     wait_us(1);
01076     *csPin = 1;
01077 
01078     /*
01079     digitalWrite(csPin, LOW); // Initiate communication
01080 
01081     // If write, bit 0 (MSB) should be 0
01082     // If single write, bit 1 should be 0
01083     spi->transfer(subAddress & 0x3F); // Send Address
01084     spi->transfer(data); // Send data
01085 
01086     digitalWrite(csPin, HIGH); // Close communication
01087     */
01088 }
01089 
01090 uint8_t LSM9DS1::SPIreadByte(DigitalOut* csPin, uint8_t subAddress)
01091 {
01092     uint8_t temp;
01093     // Use the multiple read function to read 1 byte.
01094     // Value is returned to `temp`.
01095     SPIreadBytes(csPin, subAddress, &temp, 1);
01096     return temp;
01097 }
01098 
01099 void LSM9DS1::SPIreadBytes(DigitalOut* csPin, uint8_t subAddress,
01100                            uint8_t * dest, uint8_t count)
01101 {
01102     // To indicate a read, set bit 0 (msb) of first byte to 1
01103     uint8_t rAddress = 0x80 | (subAddress & 0x3F);
01104     // Mag SPI port is different. If we're reading multiple bytes,
01105     // set bit 1 to 1. The remaining six bytes are the address to be read
01106     if ((csPin == _mAddress) && count > 1)
01107         rAddress |= 0x40;
01108 
01109     *csPin = 0;
01110 
01111     wait_us(1);
01112 
01113     spi->write(rAddress);
01114     for (int i=0; i<count; i++)
01115         dest[i] = spi->write(0xFF);
01116 
01117     wait_us(1);
01118     *csPin = 1;
01119 
01120     /*
01121     digitalWrite(csPin, LOW); // Initiate communication
01122     spi->transfer(rAddress);
01123     for (int i=0; i<count; i++)
01124     {
01125         dest[i] = spi->transfer(0x00); // Read into destination array
01126     }
01127     digitalWrite(csPin, HIGH); // Close communication
01128     */
01129 }
01130 
01131 void LSM9DS1::initI2C()
01132 {
01133     /*
01134     Wire.begin();   // Initialize I2C library
01135     */
01136 
01137     //already initialized in constructor!
01138 }
01139 
01140 // Wire.h read and write protocols
01141 void LSM9DS1::I2CwriteByte(uint8_t address, uint8_t subAddress, uint8_t data)
01142 {
01143     /*
01144     Wire.beginTransmission(address);  // Initialize the Tx buffer
01145     Wire.write(subAddress);           // Put slave register address in Tx buffer
01146     Wire.write(data);                 // Put data in Tx buffer
01147     Wire.endTransmission();           // Send the Tx buffer
01148     */
01149   //  char temp_data[2] = {subAddress, data};
01150   //  i2c.write(address, temp_data, 2);
01151 }
01152 
01153 uint8_t LSM9DS1::I2CreadByte(uint8_t address, uint8_t subAddress)
01154 {
01155     /*
01156     int timeout = LSM9DS1_COMMUNICATION_TIMEOUT;
01157     uint8_t data; // `data` will store the register data
01158 
01159     Wire.beginTransmission(address);         // Initialize the Tx buffer
01160     Wire.write(subAddress);                  // Put slave register address in Tx buffer
01161     Wire.endTransmission(true);             // Send the Tx buffer, but send a restart to keep connection alive
01162     Wire.requestFrom(address, (uint8_t) 1);  // Read one byte from slave register address
01163     while ((Wire.available() < 1) && (timeout-- > 0))
01164         delay(1);
01165 
01166     if (timeout <= 0)
01167         return 255; //! Bad! 255 will be misinterpreted as a good value.
01168 
01169     data = Wire.read();                      // Fill Rx buffer with result
01170     return data;                             // Return data read from slave register
01171     */
01172     char data;
01173     char temp[1] = {subAddress};
01174 /*
01175     i2c.write(address, temp, 1);
01176     //i2c.write(address & 0xFE);
01177     temp[1] = 0x00;
01178     i2c.write(address, temp, 1);
01179     //i2c.write( address | 0x01);
01180     int a = i2c.read(address, &data, 1);*/
01181     return data;
01182 }
01183 
01184 uint8_t LSM9DS1::I2CreadBytes(uint8_t address, uint8_t subAddress, uint8_t * dest, uint8_t count)
01185 {
01186     /*
01187     int timeout = LSM9DS1_COMMUNICATION_TIMEOUT;
01188     Wire.beginTransmission(address);   // Initialize the Tx buffer
01189     // Next send the register to be read. OR with 0x80 to indicate multi-read.
01190     Wire.write(subAddress | 0x80);     // Put slave register address in Tx buffer
01191 
01192     Wire.endTransmission(true);             // Send the Tx buffer, but send a restart to keep connection alive
01193     uint8_t i = 0;
01194     Wire.requestFrom(address, count);  // Read bytes from slave register address
01195     while ((Wire.available() < count) && (timeout-- > 0))
01196         delay(1);
01197     if (timeout <= 0)
01198         return -1;
01199 
01200     for (int i=0; i<count;)
01201     {
01202         if (Wire.available())
01203         {
01204             dest[i++] = Wire.read();
01205         }
01206     }
01207     return count;
01208     */
01209     int i;
01210     char temp_dest[count];
01211     char temp[1] = {subAddress};
01212     //i2c.write(address, temp, 1);
01213     //i2c.read(address, temp_dest, count);
01214 
01215     //i2c doesn't take uint8_ts, but rather chars so do this nasty af conversion
01216     for (i=0; i < count; i++) {
01217         dest[i] = temp_dest[i];
01218     }
01219     return count;
01220 }
01221