Home | History | Annotate | Download | only in lsm9ds0
      1 /*
      2  * Author: Jon Trulson <jtrulson (at) ics.com>
      3  * Copyright (c) 2015 Intel Corporation.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be
     14  * included in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
     20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
     21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 #pragma once
     25 
     26 #include <string>
     27 #include <mraa/common.hpp>
     28 #include <mraa/i2c.hpp>
     29 
     30 #include <mraa/gpio.hpp>
     31 
     32 #if defined(SWIGJAVA) || defined(JAVACALLBACK)
     33 #include "../IsrCallback.h"
     34 #endif
     35 
     36 #define LSM9DS0_I2C_BUS 1
     37 #define LSM9DS0_DEFAULT_XM_ADDR 0x1d
     38 #define LSM9DS0_DEFAULT_GYRO_ADDR 0x6b
     39 
     40 namespace upm {
     41 
     42   /**
     43    * @brief LSM9DS0 accelerometer library
     44    * @defgroup lsm9ds0 libupm-lsm9ds0
     45    * @ingroup i2c gpio accelerometer compass
     46    */
     47 
     48   /**
     49    * @library lsm9ds0
     50    * @sensor lsm9ds0
     51    * @comname LSM9DS0 3-axis Gyroscope, Accelerometer, and Magnetometer
     52    * @type accelerometer compass
     53    * @man sparkfun
     54    * @con i2c gpio
     55    * @web https://www.sparkfun.com/products/13033
     56    *
     57    * @brief API for the LSM9DS0 3-axis Gyroscope, Accelerometer,
     58    * and Magnetometer
     59    *
     60    * The LSM9DS0 is a system-in-package featuring a 3D digital linear
     61    * acceleration sensor, a 3D digital angular rate sensor, and a 3D
     62    * digital magnetic sensor.
     63    *
     64    * The LSM9DS0 has a linear acceleration full scale of
     65    * 2g/4g/6g/8g/16g, a magnetic field full scale of 2/4/8/12
     66    * gauss and an angular rate of 245/500/2000 dps.
     67    *
     68    * While not all of the functionality of this device is supported
     69    * initially, methods and register definitions are provided that
     70    * should allow an end user to implement whatever features are
     71    * required.
     72    *
     73    * This driver was developed on a Sparkfun 9DOF edison block.
     74    *
     75    * @snippet lsm9ds0.cxx Interesting
     76    */
     77 
     78   class LSM9DS0 {
     79   public:
     80 
     81     // NOTE: reserved registers must not be written into or permanent
     82     // damage to the device can result.  Reserved bitfields must
     83     // always be 0.
     84 
     85     // There are two sub-devices within this device - the
     86     // Accelerometer and Magnetometer (XM) and the Gyroscope (G), each
     87     // with their own I2C address.
     88 
     89     /**
     90      * LSM9DS0 Gyroscope (G) registers
     91      */
     92     typedef enum {
     93       // 0x00-0x0e reserved
     94 
     95       REG_WHO_AM_I_G            = 0x0f, // should be 0xd4
     96 
     97       // 0x10-0x1f reserved
     98 
     99       REG_CTRL_REG1_G           = 0x20,
    100       REG_CTRL_REG2_G           = 0x21,
    101       REG_CTRL_REG3_G           = 0x22,
    102       REG_CTRL_REG4_G           = 0x23,
    103       REG_CTRL_REG5_G           = 0x24,
    104 
    105       REG_REFERENCE_G           = 0x25,
    106 
    107       // 0x26 reserved
    108 
    109       REG_STATUS_REG_G          = 0x27,
    110 
    111       REG_OUT_X_L_G             = 0x28, // gyro output, X axis, LSB
    112       REG_OUT_X_H_G             = 0x29, // gyro output, X axis, MSB
    113       REG_OUT_Y_L_G             = 0x2a,
    114       REG_OUT_Y_H_G             = 0x2b,
    115       REG_OUT_Z_L_G             = 0x2c,
    116       REG_OUT_Z_H_G             = 0x2d,
    117 
    118       REG_FIFO_CTRL_REG_G       = 0x2e,
    119       REG_FIFO_SRC_REG_G        = 0x2f,
    120 
    121       REG_INT1_CFG_G            = 0x30,
    122       REG_INT1_SRC_G            = 0x31,
    123 
    124       REG_INT1_TSH_XH_G         = 0x32, // interrupt threshold registers
    125       REG_INT1_TSH_XL_G         = 0x33,
    126       REG_INT1_TSH_YH_G         = 0x34,
    127       REG_INT1_TSH_YL_G         = 0x35,
    128       REG_INT1_TSH_ZH_G         = 0x36,
    129       REG_INT1_TSH_ZL_G         = 0x37,
    130 
    131       // See fig 19 & 20 and preceeding description in the datasheet
    132       // on how to use this register
    133       REG_INT1_DURATION_G       = 0x38
    134     } REG_G_T;
    135 
    136     /**
    137      * Gyro CTRL_REG1_G bits
    138      */
    139     typedef enum {
    140       CTRL_REG1_G_YEN           = 0x01, // Y enable, odd ordering...
    141       CTRL_REG1_G_XEN           = 0x02,
    142       CTRL_REG1_G_ZEN           = 0x04,
    143       CTRL_REG1_G_PD            = 0x08, // power down (0)
    144 
    145       CTRL_REG1_G_BW0           = 0x10, // bandwidth
    146       CTRL_REG1_G_BW1           = 0x20,
    147       _CTRL_REG1_G_BW_MASK      = 3,
    148       _CTRL_REG1_G_BW_SHIFT     = 4,
    149 
    150       CTRL_REG1_G_DR0           = 0x40, // data rate
    151       CTRL_REG1_G_DR1           = 0x80,
    152       _CTRL_REG1_G_DR_MASK      = 3,
    153       _CTRL_REG1_G_DR_SHIFT     = 6,
    154 
    155       // The following are synthetic register and shift/mask
    156       // definitions.  Together both BW and DR setup the device for a
    157       // specific output data rate (ODR) and cutoff frequency. These
    158       // definitions allow us to use a more informative configuration
    159       // for these 4 bits, rather than having the user go to the
    160       // datasheet to figure out what to put for those values in order
    161       // to get the desired ODR/cutoff.  These are the values we will
    162       // use in this driver.
    163 
    164       CTRL_REG1_G_ODR0          = 0x10, // BW0
    165       CTRL_REG1_G_ODR1          = 0x20, // BW1
    166       CTRL_REG1_G_ODR2          = 0x40, // DR0
    167       CTRL_REG1_G_ODR3          = 0x80, // DR1
    168       _CTRL_REG1_G_ODR_MASK     = 15,
    169       _CTRL_REG1_G_ODR_SHIFT    = 4
    170     } CTRL_REG1_G_BITS_T;
    171 
    172     /**
    173      * CRTL_REG1_G_ODR values
    174      */
    175     typedef enum {
    176       G_ODR_95_12_5             = 0, // ODR = 95Hz, cutoff = 12.5
    177       G_ODR_95_25               = 1, // ODR = 95Hz, cutoff = 25
    178       // Other two (2 and 3) are the same (95_25)
    179 
    180       G_ODR_190_12_5            = 4,
    181       G_ODR_190_25              = 5,
    182       G_ODR_190_50              = 6,
    183       G_ODR_190_70              = 7,
    184 
    185       G_ODR_380_20              = 8,
    186       G_ODR_380_25              = 9,
    187       G_ODR_380_50              = 10,
    188       G_ODR_380_100             = 11,
    189 
    190       G_ODR_760_30              = 12,
    191       G_ODR_760_35              = 13,
    192       G_ODR_760_50              = 14,
    193       G_ODR_760_100             = 15
    194     } G_ODR_T;
    195 
    196     /**
    197      * Gyro CTRL_REG2_G bits
    198      */
    199     typedef enum {
    200       CTRL_REG2_G_HPCF0         = 0x01, // high-pass cutoff freq
    201       CTRL_REG2_G_HPCF1         = 0x02,
    202       CTRL_REG2_G_HPCF2         = 0x04,
    203       CTRL_REG2_G_HPCF3         = 0x08,
    204       _CTRL_REG2_G_HPCF_MASK    = 15,
    205       _CTRL_REG2_G_HPCF_SHIFT   = 0,
    206 
    207       CTRL_REG2_G_HPM0          = 0x10, // high-pass filter mode
    208       CTRL_REG2_G_HPM1          = 0x20,
    209       _CTRL_REG2_G_HPM_MASK     = 3,
    210       _CTRL_REG2_G_HPM_SHIFT    = 4,
    211 
    212       // 0x40, 0x80 reserved
    213     } CTRL_REG2_G_BITS_T;
    214 
    215     /**
    216      * CRTL_REG2_G_HPCF values
    217      *
    218      * See table 26 in the datasheet, as these depend on your data
    219      * rate (ODR).  We will label these according to the 95Hz column,
    220      * but of course the actual cutoff frequency depends on ODR.
    221      */
    222     typedef enum {
    223       G_HPCF_7_2                = 0, // 7.2 Hz (if ODR is 95Hz)
    224       G_HPCF_3_5                = 1,
    225       G_HPCF_1_8                = 2,
    226       G_HPCF_0_9                = 3, // 0.9Hz
    227       G_HPCF_0_45               = 4,
    228       G_HPCF_0_18               = 5,
    229       G_HPCF_0_09               = 6,
    230       G_HPCF_0_045              = 7,
    231       G_HPCF_0_018              = 8,
    232       G_HPCF_0_009              = 9
    233 
    234       // 10-15 unused
    235     } G_HPCF_T;
    236 
    237     /**
    238      * CRTL_REG2_G_HPM values
    239      *
    240      */
    241     typedef enum {
    242       G_HPM_NORMAL_RESET_HPF    = 0, // reset reading (HP_RESET_FILTER)
    243       G_HPM_REFERENCE           = 1, // REF signal for filtering
    244       G_HPM_NORMAL              = 2, // normal mode
    245       G_HPM_AUTORESET_ON_INTR   = 3  // autoreset in interrupt event
    246     } G_HPM_T;
    247 
    248     /**
    249      * Gyro CTRL_REG3_G bits (interrupt G config)
    250      */
    251     typedef enum {
    252       CTRL_REG3_G_I2_EMPTY      = 0x01, // FIFO empty on DRDY_G
    253       CTRL_REG3_G_I2_ORUN       = 0x02, // FIFO Overrun intr
    254       CTRL_REG3_G_I2_WTM        = 0x04, // FIFO watermark intr
    255       CTRL_REG3_G_I2_DRDY       = 0x08, // data ready on DRDY_G
    256       CTRL_REG3_G_PP_OD         = 0x10, // push-pull/open drain
    257       CTRL_REG3_G_H_LACTIVE     = 0x20,
    258       CTRL_REG3_G_I1_BOOT       = 0x40,
    259       CTRL_REG3_G_I1_INT1       = 0x80, // intr enable on INT_G pin
    260     } CTRL_REG3_G_BITS_T;
    261 
    262     /**
    263      * Gyro CTRL_REG4_G bits
    264      */
    265     typedef enum {
    266       CTRL_REG4_G_SIM           = 0x01, // SPI mode selection
    267 
    268       CTRL_REG4_G_ST0           = 0x02, // self test enables
    269       CTRL_REG4_G_ST1           = 0x04,
    270       _CTRL_REG4_G_ST_MASK      = 3,
    271       _CTRL_REG4_G_ST_SHIFT     = 1,
    272 
    273       // 0x08 reserved
    274 
    275       CTRL_REG4_G_FS0           = 0x10, // full scale selection
    276       CTRL_REG4_G_FS1           = 0x20,
    277       _CTRL_REG4_G_FS_MASK      = 3,
    278       _CTRL_REG4_G_FS_SHIFT     = 4,
    279 
    280       CTRL_REG4_G_BLE           = 0x40, // big/little endian data selection
    281       CTRL_REG4_G_BDU           = 0x80  // block data updates
    282     } CTRL_REG4_G_BITS_T;
    283 
    284     /**
    285      * CRTL_REG4_G_ST values
    286      *
    287      */
    288     typedef enum {
    289       G_ST_NORMAL               = 0, // normal mode
    290       G_ST_SELFTEST0            = 1, // x+, y-, z-
    291 
    292       // 2, reserved
    293 
    294       G_ST_SELFTEST1            = 3  // x-, y+, z+
    295     } G_ST_T;
    296 
    297     /**
    298      * CRTL_REG4_G_FS values
    299      *
    300      */
    301     typedef enum {
    302       G_FS_245                  = 0, // 245 deg/sec
    303       G_FS_500                  = 1,
    304       G_FS_2000                 = 2
    305       // 3 is also 2000
    306     } G_FS_T;
    307 
    308     /**
    309      * Gyro CTRL_REG5_G bits
    310      */
    311     typedef enum {
    312       CTRL_REG5_G_OUTSEL0       = 0x01, // see fig. 18 in the datasheet
    313       CTRL_REG5_G_OUTSEL1       = 0x02,
    314       _CTRL_REG5_G_OUTSEL_MASK  = 3,
    315       _CTRL_REG5_G_OUTSEL_SHIFT = 0,
    316 
    317       CTRL_REG5_G_INT1SEL0      = 0x04, // see fig. 18 in the datasheet
    318       CTRL_REG5_G_INT1SEL1      = 0x08,
    319       _CTRL_REG5_G_INT1SEL_MASK = 3,
    320       _CTRL_REG5_G_INT1SEL_SHIFT = 2,
    321 
    322       CTRL_REG5_G_HPEN          = 0x10, // HPF enable
    323 
    324       // 0x20 reserved
    325 
    326       CTRL_REG5_G_FIFO_EN       = 0x40,
    327       CTRL_REG5_G_BOOT          = 0x80  // reboot memory content
    328     } CTRL_REG5_G_BITS_T;
    329 
    330 
    331     /**
    332      * CRTL_REG5_G_OUTSEL and INT1SEL values.  See Figure 18 in the
    333      * datasheet.
    334      */
    335     typedef enum {
    336       G_INT1OUTSEL_0            = 0,
    337       G_INT1OUTSEL_1            = 1,
    338       G_INT1OUTSEL_2            = 2,
    339       G_INT1OUTSEL_3            = 3
    340     } G_INT1OUTSEL_T;
    341 
    342     /**
    343      * Gyro STATUS_REG_G bits
    344      */
    345     typedef enum {
    346       STATUS_REG_G_XDA          = 0x01, // X axis data available
    347       STATUS_REG_G_YDA          = 0x02,
    348       STATUS_REG_G_ZDA          = 0x04,
    349       STATUS_REG_G_ZYXDA        = 0x08, // X, Y, and Z data available
    350 
    351       STATUS_REG_G_XOR          = 0x10, // X data overrun
    352       STATUS_REG_G_YOR          = 0x20,
    353       STATUS_REG_G_ZOR          = 0x40,
    354       STATUS_REG_G_ZYXOR        = 0x80
    355     } STATUS_REG_G_BITS_T;
    356 
    357     /**
    358      * Gyro FIFO_CTRL_REG_G bits
    359      */
    360     typedef enum {
    361       FIFO_CTRL_REG_G_WTM0      = 0x01, // FIFO watermark
    362       FIFO_CTRL_REG_G_WTM1      = 0x02,
    363       FIFO_CTRL_REG_G_WTM2      = 0x04,
    364       FIFO_CTRL_REG_G_WTM3      = 0x08,
    365       FIFO_CTRL_REG_G_WTM4      = 0x10,
    366       _FIFO_CTRL_REG_G_WTM_MASK = 31,
    367       _FIFO_CTRL_REG_G_WTM_SHIFT = 0,
    368 
    369       FIFO_CTRL_REG_G_FM0       = 0x20, // FIFO mode config
    370       FIFO_CTRL_REG_G_FM1       = 0x40,
    371       FIFO_CTRL_REG_G_FM2       = 0x80,
    372       _FIFO_CTRL_REG_G_FM_MASK  = 7,
    373       _FIFO_CTRL_REG_G_FM_SHIFT = 5,
    374     } FIFO_CTRL_REG_G_T;
    375 
    376     // FIFO_CTRL_REG_G_WTM (FIFO watermark) is just a numeric value
    377     // between 0-31, so we won't enumerate those values.
    378 
    379     /**
    380      * FIFO_CTRL_REG_G_FM values (FIFO Modes)
    381      *
    382      */
    383     typedef enum {
    384       G_FM_BYPASS               = 0,
    385       G_FM_FIFO                 = 1,
    386       G_FM_STREAM               = 2,
    387       G_FM_STREAM2FIFO          = 3,
    388       G_FM_BYPASS2STREAM        = 4
    389 
    390       // 5-7 unused
    391     } G_FM_T;
    392 
    393     /**
    394      * FIFO_SRC_REG_G bits
    395      *
    396      */
    397     typedef enum {
    398       FIFO_CTRL_REG_G_FSS0      = 0x01, // FIFO stored data level
    399       FIFO_CTRL_REG_G_FSS1      = 0x02,
    400       FIFO_CTRL_REG_G_FSS2      = 0x04,
    401       FIFO_CTRL_REG_G_FSS3      = 0x08,
    402       FIFO_CTRL_REG_G_FSS4      = 0x10,
    403       _FIFO_CTRL_REG_G_FSS_MASK = 31,
    404       _FIFO_CTRL_REG_G_FSS_SHIFT = 0,
    405 
    406       FIFO_CTRL_REG_G_EMPTY     = 0x20, // FIFO empty
    407       FIFO_CTRL_REG_G_OVRN      = 0x40, // FIFO overrun
    408       FIFO_CTRL_REG_G_WTM       = 0x80  // watermark status
    409     } FIFO_SRC_REG_G_BITS_T;
    410 
    411     /**
    412      * INT1_CFG_G bits
    413      *
    414      */
    415     typedef enum {
    416       INT1_CFG_G_XLIE           = 0x01, // X Low event interrupt enable
    417       INT1_CFG_G_XHIE           = 0x02, // X High event interrupt enable
    418       INT1_CFG_G_YLIE           = 0x04,
    419       INT1_CFG_G_YHIE           = 0x08,
    420       INT1_CFG_G_ZLIE           = 0x10,
    421       INT1_CFG_G_ZHIE           = 0x20,
    422 
    423       INT1_CFG_G_LIR            = 0x40, // latch interrupt request
    424       INT1_CFG_G_ANDOR          = 0x80  // OR or AND interrupt events
    425     } INT1_CFG_G_BITS_T;
    426 
    427     /**
    428      * INT1_SRC_G bits
    429      *
    430      */
    431     typedef enum {
    432       INT1_SRC_G_XL             = 0x01, // X low interrupt
    433       INT1_SRC_G_XH             = 0x02, // X high interrupt
    434       INT1_SRC_G_YL             = 0x04,
    435       INT1_SRC_G_YH             = 0x08,
    436       INT1_SRC_G_ZL             = 0x10,
    437       INT1_SRC_G_ZH             = 0x20,
    438 
    439       INT1_SRC_G_IA             = 0x40 // interrupt active
    440 
    441       // 0x80 reserved
    442     } INT1_SRC_G_BITS_T;
    443 
    444     // The following registers are for the Accelerometer (A/X),
    445     // Magnetometer (M), and Temperature device.
    446 
    447     /**
    448      * LSM9DS0 Accelerometer (X) and Magnetometer (M) registers
    449      */
    450     typedef enum {
    451       // 0x00-0x04 reserved
    452 
    453       REG_OUT_TEMP_L_XM         = 0x05, // temperature
    454       REG_OUT_TEMP_H_XM         = 0x06,
    455 
    456       REG_STATUS_REG_M          = 0x07,
    457 
    458       REG_OUT_X_L_M             = 0x08, // magnetometer outputs
    459       REG_OUT_X_H_M             = 0x09,
    460       REG_OUT_Y_L_M             = 0x0a,
    461       REG_OUT_Y_H_M             = 0x0b,
    462       REG_OUT_Z_L_M             = 0x0c,
    463       REG_OUT_Z_H_M             = 0x0d,
    464 
    465       // 0x0e reserved
    466 
    467       REG_WHO_AM_I_XM           = 0x0f,
    468 
    469       // 0x10, 0x11 reserved
    470 
    471       REG_INT_CTRL_REG_M        = 0x12,
    472       REG_INT_SRC_REG_M         = 0x13,
    473 
    474       REG_INT_THS_L_M           = 0x14, // magnetometer threshold
    475       REG_INT_THS_H_M           = 0x15,
    476 
    477       REG_OFFSET_X_L_M          = 0x16,
    478       REG_OFFSET_X_H_M          = 0x17,
    479       REG_OFFSET_Y_L_M          = 0x18,
    480       REG_OFFSET_Y_H_M          = 0x19,
    481       REG_OFFSET_Z_L_M          = 0x1a,
    482       REG_OFFSET_Z_H_M          = 0x1b,
    483 
    484       REG_REFERENCE_X           = 0x1c,
    485       REG_REFERENCE_Y           = 0x1d,
    486       REG_REFERENCE_Z           = 0x1e,
    487 
    488       REG_CTRL_REG0_XM          = 0x1f,
    489       REG_CTRL_REG1_XM          = 0x20,
    490       REG_CTRL_REG2_XM          = 0x21,
    491       REG_CTRL_REG3_XM          = 0x22,
    492       REG_CTRL_REG4_XM          = 0x23,
    493       REG_CTRL_REG5_XM          = 0x24,
    494       REG_CTRL_REG6_XM          = 0x25,
    495       REG_CTRL_REG7_XM          = 0x26,
    496 
    497       REG_STATUS_REG_A          = 0x27,
    498 
    499       REG_OUT_X_L_A             = 0x28, // accelerometer outputs
    500       REG_OUT_X_H_A             = 0x29,
    501       REG_OUT_Y_L_A             = 0x2a,
    502       REG_OUT_Y_H_A             = 0x2b,
    503       REG_OUT_Z_L_A             = 0x2c,
    504       REG_OUT_Z_H_A             = 0x2d,
    505 
    506       REG_FIFO_CTRL_REG         = 0x2e,
    507       REG_FIFO_SRC_REG          = 0x2f,
    508 
    509       REG_INT_GEN_1_REG         = 0x30,
    510       REG_INT_GEN_1_SRC         = 0x31,
    511       REG_INT_GEN_1_THS         = 0x32,
    512       REG_INT_GEN_1_DURATION    = 0x33,
    513 
    514       REG_INT_GEN_2_REG         = 0x34,
    515       REG_INT_GEN_2_SRC         = 0x35,
    516       REG_INT_GEN_2_THS         = 0x36,
    517       REG_INT_GEN_2_DURATION    = 0x37,
    518 
    519       REG_CLICK_CFG             = 0x38,
    520       REG_CLICK_SRC             = 0x39,
    521       REG_CLICK_THS             = 0x3a,
    522 
    523       REG_TIME_LIMIT            = 0x3b,
    524       REG_TIME_LATENCY          = 0x3c,
    525       REG_TIME_WINDOW           = 0x3d,
    526 
    527       REG_ACT_THS               = 0x3e,
    528       REG_ACT_DUR               = 0x3f
    529     } REG_XM_T;
    530 
    531     /**
    532      * XM STATUS_REG_M bits
    533      */
    534     typedef enum {
    535       STATUS_REG_M_XMDA         = 0x01, // X mag axis data available
    536       STATUS_REG_M_YMDA         = 0x02,
    537       STATUS_REG_M_ZMDA         = 0x04,
    538       STATUS_REG_M_ZYXMDA       = 0x08, // X, Y, and Z mag data available
    539 
    540       STATUS_REG_M_XMOR         = 0x10, // X mag data overrun
    541       STATUS_REG_M_YMOR         = 0x20,
    542       STATUS_REG_M_ZMOR         = 0x40,
    543       STATUS_REG_M_ZYXMOR       = 0x80
    544     } STATUS_REG_M_BITS_T;
    545 
    546     /**
    547      * INT_CTRL_REG_M bits
    548      */
    549     typedef enum {
    550       INT_CTRL_REG_M_MIEN       = 0x01, // mag interrupt enable
    551       INT_CTRL_REG_M_4D         = 0x02,
    552       INT_CTRL_REG_M_IEL        = 0x04, // latch intr request
    553       INT_CTRL_REG_M_IEA        = 0x08,
    554       INT_CTRL_REG_M_PP_OD      = 0x10, // push-pull/open drian
    555       INT_CTRL_REG_M_ZMIEN      = 0x20, // Z mag axis interrupt recognition
    556       INT_CTRL_REG_M_YMIEN      = 0x40,
    557       INT_CTRL_REG_M_XMIEN      = 0x80
    558     } INT_CTRL_REG_M_BITS_T;
    559 
    560     /**
    561      * INT_SRC_REG_M bits
    562      */
    563     typedef enum {
    564       INT_SRC_REG_M_MINT        = 0x01,
    565       INT_SRC_REG_M_MROI        = 0x02,
    566       INT_SRC_REG_M_NTH_Z       = 0x04,
    567       INT_SRC_REG_M_NTH_Y       = 0x08,
    568       INT_SRC_REG_M_NTH_X       = 0x10,
    569       INT_SRC_REG_M_PTH_Z       = 0x20,
    570       INT_SRC_REG_M_PTH_Y       = 0x40,
    571       INT_SRC_REG_M_PTH_X       = 0x80
    572     } INT_SRC_REG_M_BITS_T;
    573 
    574 
    575     /**
    576      * CTRL_REG0_XM bits
    577      */
    578     typedef enum {
    579       CTRL_REG0_XM_HPIS2        = 0x01, // HPF enable for int generator 2
    580       CTRL_REG0_XM_HPIS1        = 0x02,
    581 
    582       CTRL_REG0_XM_HP_CLICK     = 0x04, // HPF enable for click
    583 
    584       // 0x08,0x10 reserved
    585 
    586       CTRL_REG0_XM_WTM_LEN      = 0x20, // watermark enable
    587       CTRL_REG0_XM_FIFO_EN      = 0x40, // FIFO enable
    588       CTRL_REG0_XM_BOOT         = 0x80  // reboot memory content
    589     } CTRL_REG0_XM_BITS_T;
    590 
    591     /**
    592      * CTRL_REG1_XM bits
    593      */
    594     typedef enum {
    595       CTRL_REG1_XM_AXEN         = 0x01, // accelerometer x axis enable
    596       CTRL_REG1_XM_AYEN         = 0x02,
    597       CTRL_REG1_XM_AZEN         = 0x03,
    598 
    599       CTRL_REG1_XM_BDU          = 0x04, // block data update
    600 
    601       CTRL_REG1_XM_AODR0        = 0x10, // accelerometer output data rate
    602       CTRL_REG1_XM_AODR1        = 0x20,
    603       CTRL_REG1_XM_AODR2        = 0x40,
    604       CTRL_REG1_XM_AODR3        = 0x80,
    605       _CTRL_REG1_XM_AODR_MASK   = 15,
    606       _CTRL_REG1_XM_AODR_SHIFT  = 4
    607     } CTRL_REG1_XM_BITS_T;
    608 
    609     /**
    610      * CTRL_REG1_XM_AODR values
    611      */
    612     typedef enum {
    613       XM_AODR_PWRDWN            = 0, // power down mode
    614       XM_AODR_3_125             = 1, // 3.125 Hz
    615       XM_AODR_6_25              = 2,
    616       XM_AODR_12_5              = 3,
    617       XM_AODR_25                = 4, // 25Hz
    618       XM_AODR_50                = 5,
    619       XM_AODR_100               = 6,
    620       XM_AODR_200               = 7,
    621       XM_AODR_400               = 8,
    622       XM_AODR_800               = 9,
    623       XM_AODR_1000              = 10
    624       // 11-15 unused
    625     } XM_AODR_T;
    626 
    627     /**
    628      * CTRL_REG2_XM bits
    629      */
    630     typedef enum {
    631       CTRL_REG2_XM_SIM         = 0x01,
    632 
    633       CTRL_REG2_XM_AST0        = 0x02, // accel self-test enable
    634       CTRL_REG2_XM_AST1        = 0x04,
    635       _CTRL_REG2_XM_AST_MASK   = 3,
    636       _CTRL_REG2_XM_AST_SHIFT  = 1,
    637 
    638       CTRL_REG2_XM_AFS0        = 0x08, // accel full scale
    639       CTRL_REG2_XM_AFS1        = 0x10,
    640       CTRL_REG2_XM_AFS2        = 0x20,
    641       _CTRL_REG2_XM_AFS_MASK   = 7,
    642       _CTRL_REG2_XM_AFS_SHIFT  = 3,
    643 
    644       CTRL_REG2_XM_ABW0        = 0x40, // accel anti-alias filter bandwidth
    645       CTRL_REG2_XM_ABW1        = 0x80,
    646       _CTRL_REG2_XM_ABW_MASK   = 3,
    647       _CTRL_REG2_XM_ABW_SHIFT  = 6
    648     } CTRL_REG2_XM_BITS_T;
    649 
    650     /**
    651      * CTRL_REG2_XM_AST values
    652      */
    653     typedef enum {
    654       XM_AST_NORMAL            = 0,
    655       XM_AST_POS_SIGN          = 1,
    656       XM_AST_NEG_SIGN          = 2
    657       // 3 not allowed
    658     } XM_AST_T;
    659 
    660     /**
    661      * CTRL_REG2_XM_AFS (accel full scale) values
    662      */
    663     typedef enum {
    664       XM_AFS_2                 = 0, // 2g
    665       XM_AFS_4                 = 1,
    666       XM_AFS_6                 = 2,
    667       XM_AFS_8                 = 3,
    668       XM_AFS_16                = 4
    669 
    670       // 5-7 not used
    671     } XM_AFS_T;
    672 
    673     /**
    674      * CTRL_REG2_XM_ABW (accel anti-alias filter bandwidth) values
    675      */
    676     typedef enum {
    677       XM_ABW_773               = 0, // 773Hz
    678       XM_ABW_194               = 1, // these two might be inverted (typo in ds)
    679       XM_ABW_362               = 2,
    680       XM_ABW_50                = 3
    681     } XM_ABW_T;
    682 
    683     /**
    684      * CTRL_REG3_XM bits
    685      */
    686     typedef enum {
    687       CTRL_REG3_XM_P1_EMPTY    = 0x01, // INT1_XM pin enables
    688       CTRL_REG3_XM_P1_DRDYM    = 0x02,
    689       CTRL_REG3_XM_P1_DRDYA    = 0x04,
    690       CTRL_REG3_XM_P1_INTM     = 0x08,
    691       CTRL_REG3_XM_P1_INT2     = 0x10,
    692       CTRL_REG3_XM_P1_INT1     = 0x20,
    693       CTRL_REG3_XM_P1_TAP      = 0x40,
    694       CTRL_REG3_XM_P1_BOOT     = 0x80
    695     } CTRL_REG3_XM_BITS_T;
    696 
    697     /**
    698      * CTRL_REG4_XM bits
    699      */
    700     typedef enum {
    701       CTRL_REG4_XM_P2_WTM      = 0x01, // INT2_XM pin enables
    702       CTRL_REG4_XM_P2_OVERRUN  = 0x02,
    703       CTRL_REG4_XM_P2_DRDYM    = 0x04,
    704       CTRL_REG4_XM_P2_DRDYA    = 0x08,
    705       CTRL_REG4_XM_P2_INTM     = 0x10,
    706       CTRL_REG4_XM_P2_INT2     = 0x20,
    707       CTRL_REG4_XM_P2_INT1     = 0x40,
    708       CTRL_REG4_XM_P2_TAP      = 0x80
    709     } CTRL_REG4_XM_BITS_T;
    710 
    711     /**
    712      * CTRL_REG5_XM bits
    713      */
    714     typedef enum {
    715       CTRL_REG5_XM_LIR1        = 0x01, // latch intr 1
    716       CTRL_REG5_XM_LIR2        = 0x02, // latch intr 2
    717 
    718       CTRL_REG5_XM_ODR0        = 0x04, // mag output data rate
    719       CTRL_REG5_XM_ODR1        = 0x08,
    720       CTRL_REG5_XM_ODR2        = 0x10,
    721       _CTRL_REG5_XM_ODR_MASK   = 7,
    722       _CTRL_REG5_XM_ODR_SHIFT  = 2,
    723 
    724       CTRL_REG5_XM_RES0        = 0x20, // mag resolution
    725       CTRL_REG5_XM_RES1        = 0x40,
    726       _CTRL_REG5_XM_RES_MASK   = 3,
    727       _CTRL_REG5_XM_RES_SHIFT  = 5,
    728 
    729       CTRL_REG5_XM_TEMP_EN     = 0x80  // temp sensor enable
    730     } CTRL_REG5_XM_BITS_T;
    731 
    732     /**
    733      * CTRL_REG5_XM_ODR (magnetometer output data rate) values
    734      */
    735     typedef enum {
    736       XM_ODR_3_125             = 0, // 3.125Hz
    737       XM_ODR_6_25              = 1,
    738       XM_ODR_12_5              = 2,
    739       XM_ODR_25                = 3,
    740       XM_ODR_50                = 4,
    741       XM_ODR_100               = 5
    742 
    743       // 6, 7 reserved
    744     } XM_ODR_T;
    745 
    746     /**
    747      * CTRL_REG5_XM_RES (magnetometer resolution) values
    748      */
    749     typedef enum {
    750       XM_RES_LOW               = 0, // low resolution
    751 
    752       // 1, 2 reserved
    753 
    754       XM_RES_HIGH              = 3,
    755     } XM_RES_T;
    756 
    757     /**
    758      * CTRL_REG6_XM bits
    759      */
    760     typedef enum {
    761       // 0x01-0x10 reserved
    762 
    763       CTRL_REG6_XM_MFS0        = 0x20,
    764       CTRL_REG6_XM_MFS1        = 0x40,
    765       _CTRL_REG6_XM_MFS_MASK   = 3,
    766       _CTRL_REG6_XM_MFS_SHIFT  = 5
    767 
    768       // 0x80 reserved
    769     } CTRL_REG6_XM_BITS_T;
    770 
    771     /**
    772      * CTRL_REG6_XM_MFS (magnetometer full scale) values
    773      */
    774     typedef enum {
    775       XM_MFS_2                 = 0, // +/- 2 gauss
    776       XM_MFS_4                 = 1,
    777       XM_MFS_8                 = 2,
    778       XM_MFS_12                = 3
    779     } XM_MFS_T;
    780 
    781     /**
    782      * CTRL_REG7_XM bits
    783      */
    784     typedef enum {
    785       CTRL_REG7_XM_MD0         = 0x01, // mag sensor mode
    786       CTRL_REG7_XM_MD1         = 0x02,
    787       _CTRL_REG7_XM_MD_MASK    = 3,
    788       _CTRL_REG7_XM_MD_SHIFT   = 0,
    789 
    790       CTRL_REG7_XM_MLP         = 0x04, // mag low power mode
    791 
    792       // 0x08, 0x10 reserved
    793 
    794       CTRL_REG7_XM_AFDS        = 0x20, // filtered acceleration data
    795 
    796       CTRL_REG7_XM_AHPM0       = 0x40, // accel HPF selection
    797       CTRL_REG7_XM_AHPM1       = 0x80,
    798       _CTRL_REG7_XM_AHPM_MASK  = 3,
    799       _CTRL_REG7_XM_AHPM_SHIFT = 6
    800     } CTRL_REG7_XM_BITS_T;
    801 
    802     /**
    803      * CTRL_REG7_XM_MD (magnetometer sensor mode) values
    804      */
    805     typedef enum {
    806       XM_MD_CONTINUOUS         = 0, // continuous conversion
    807       XM_MD_SINGLE             = 1, // single conversion
    808       XM_MD_POWERDOWN          = 2  // power down mode
    809       // 3 is also power down mode, for some odd reason
    810     } XM_MD_T;
    811 
    812     /**
    813      * CTRL_REG7_AHPM_MD (accel high-pass filter mode) values
    814      */
    815     typedef enum {
    816       // XM_AHPM_NORMAL_REF: Normal mode (resets x, y and z-axis
    817       // reading REFERENCE_X (1Ch), REFERENCE_Y (1Dh) and REFERENCE_Y
    818       // (1Dh) registers respectively)
    819 
    820       XM_AHPM_NORMAL_REF       = 0,
    821       XM_AHPM_REFERENCE        = 1,
    822       XM_AHPM_NORMAL           = 2,
    823       XM_AHPM_AUTORESET        = 3  // autoreset on interrupt
    824     } XM_AHPM_T;
    825 
    826     /**
    827      * XM STATUS_REG_A bits
    828      */
    829     typedef enum {
    830       STATUS_REG_A_XADA         = 0x01, // X accel axis data available
    831       STATUS_REG_A_YADA         = 0x02,
    832       STATUS_REG_A_ZADA         = 0x04,
    833       STATUS_REG_A_ZYXADA       = 0x08, // X, Y, and Z accel data available
    834 
    835       STATUS_REG_A_XAOR         = 0x10, // X accel data overrun
    836       STATUS_REG_A_YAOR         = 0x20,
    837       STATUS_REG_A_ZAOR         = 0x40,
    838       STATUS_REG_A_ZYXAOR       = 0x80
    839     } STATUS_REG_A_BITS_T;
    840 
    841     /**
    842      * XM FIFO_CTRL_REG bits
    843      */
    844     typedef enum {
    845       FIFO_CTRL_REG_FTH0        = 0x01, // FIFO watermark/threshold
    846       FIFO_CTRL_REG_FTH1        = 0x02,
    847       FIFO_CTRL_REG_FTH2        = 0x04,
    848       FIFO_CTRL_REG_FTH3        = 0x08,
    849       FIFO_CTRL_REG_FTH4        = 0x10,
    850       _FIFO_CTRL_REG_FTH_MASK   = 31,
    851       _FIFO_CTRL_REG_FTH_SHIFT  = 0,
    852 
    853       FIFO_CTRL_REG_FM0         = 0x20, // FIFO mode config
    854       FIFO_CTRL_REG_FM1         = 0x40,
    855       FIFO_CTRL_REG_FM2         = 0x80,
    856       _FIFO_CTRL_REG_FM_MASK    = 7,
    857       _FIFO_CTRL_REG_FM_SHIFT   = 5,
    858     } FIFO_CTRL_REG_T;
    859 
    860     // FIFO_CTRL_REG_FTH (FIFO watermark/threshold) is just a numeric
    861     // value between 0-31, so we won't enumerate those values.
    862 
    863     /**
    864      * XM FIFO_CTRL_REG_FM values (FIFO Modes)
    865      *
    866      */
    867     typedef enum {
    868       FM_BYPASS                 = 0,
    869       FM_FIFO                   = 1,
    870       FM_STREAM                 = 2,
    871       FM_STREAM2FIFO            = 3,
    872       FM_BYPASS2STREAM          = 4
    873 
    874       // 5-7 unused
    875     } FM_T;
    876 
    877     /**
    878      * FIFO_SRC_REG bits
    879      *
    880      */
    881     typedef enum {
    882       FIFO_CTRL_REG_FSS0        = 0x01, // FIFO stored data level
    883       FIFO_CTRL_REG_FSS1        = 0x02,
    884       FIFO_CTRL_REG_FSS2        = 0x04,
    885       FIFO_CTRL_REG_FSS3        = 0x08,
    886       FIFO_CTRL_REG_FSS4        = 0x10,
    887       _FIFO_CTRL_REG_FSS_MASK   = 31,
    888       _FIFO_CTRL_REG_FSS_SHIFT  = 0,
    889 
    890       FIFO_CTRL_REG_EMPTY       = 0x20, // FIFO empty
    891       FIFO_CTRL_REG_OVRN        = 0x40, // FIFO overrun
    892       FIFO_CTRL_REG_WTM         = 0x80  // watermark status
    893     } FIFO_SRC_REG_BITS_T;
    894 
    895     /**
    896      * INT_GEN_1_REG and INT_GEN_2_REG (GEN_X) bits
    897      *
    898      */
    899     typedef enum {
    900       INT_GEN_X_REG_XLIE_XDOWNE = 0x01, // enable intr on X low or dir recog
    901       INT_GEN_X_REG_XHIE_XUPE   = 0x02,
    902       INT_GEN_X_REG_YLIE_YDOWNE = 0x04,
    903       INT_GEN_X_REG_YHIE_YUPE   = 0x08,
    904       INT_GEN_X_REG_ZLIE_ZDOWNE = 0x10,
    905       INT_GEN_X_REG_ZHIE_ZUPE   = 0x20,
    906       INT_GEN_X_REG_6D          = 0x40, // enable 6D direction function
    907       INT_GEN_X_REG_AOI         = 0x80  // AND/OR combination of intrs
    908     } INT_GEN_X_REG_BITS_T;
    909 
    910     /**
    911      * INT_GEN_1_SRC and INT_GEN_2_SRC (GEN_X) bits
    912      *
    913      */
    914     typedef enum {
    915       INT_GEN_X_SRC_XL          = 0x01,
    916       INT_GEN_X_SRC_XH          = 0x02,
    917       INT_GEN_X_SRC_YL          = 0x04,
    918       INT_GEN_X_SRC_YH          = 0x08,
    919       INT_GEN_X_SRC_ZL          = 0x10,
    920       INT_GEN_X_SRC_ZH          = 0x20,
    921       INT_GEN_X_SRC_IA          = 0x40
    922       // 0x80 reserved
    923     } INT_GEN_X_SRC_BITS_T;
    924 
    925     /**
    926      * INT_GEN_1_THS and INT_GEN_2_THS (GEN_X) bits
    927      *
    928      */
    929     typedef enum {
    930       INT_GEN_X_THS0            = 0x01, // interrupt threshold
    931       INT_GEN_X_THS1            = 0x02,
    932       INT_GEN_X_THS2            = 0x04,
    933       INT_GEN_X_THS3            = 0x08,
    934       INT_GEN_X_THS4            = 0x10,
    935       INT_GEN_X_THS5            = 0x20,
    936       INT_GEN_X_THS6            = 0x40,
    937       _INT_GEN_X_THS_MASK       = 127,
    938       _INT_GEN_X_THS_SHIFT      = 0
    939       // 0x80 reserved
    940     } INT_GEN_X_THS_BITS_T;
    941 
    942     /**
    943      * INT_GEN_1_DUR and INT_GEN_2_DUR (GEN_X) bits
    944      *
    945      */
    946     typedef enum {
    947       INT_GEN_X_DUR0            = 0x01, // interrupt duration
    948       INT_GEN_X_DUR1            = 0x02,
    949       INT_GEN_X_DUR2            = 0x04,
    950       INT_GEN_X_DUR3            = 0x08,
    951       INT_GEN_X_DUR4            = 0x10,
    952       INT_GEN_X_DUR5            = 0x20,
    953       INT_GEN_X_DUR6            = 0x40,
    954       _INT_GEN_X_DUR_MASK       = 127,
    955       _INT_GEN_X_DUR_SHIFT      = 0
    956       // 0x80 reserved
    957     } INT_GEN_X_DUR_BITS_T;
    958 
    959     /**
    960      * CLICK_CONFIG bits
    961      *
    962      */
    963     typedef enum {
    964       CLICK_CONFIG_XS           = 0x01, // enable intr single click x
    965       CLICK_CONFIG_XD           = 0x02, // enable intr double click x
    966       CLICK_CONFIG_YS           = 0x04,
    967       CLICK_CONFIG_YD           = 0x08,
    968       CLICK_CONFIG_ZS           = 0x10,
    969       CLICK_CONFIG_ZD           = 0x20
    970       // 0x40, 0x80 reserved
    971     } CLICK_CONFIG_BITS_T;
    972 
    973     /**
    974      * CLICK_SRC bits
    975      *
    976      */
    977     typedef enum {
    978       CLICK_SRC_X               = 0x01,
    979       CLICK_SRC_Y               = 0x02,
    980       CLICK_SRC_Z               = 0x04,
    981       CLICK_SRC_SIGN            = 0x08,
    982       CLICK_SRC_SCLICK          = 0x10,
    983       CLICK_SRC_DCLICK          = 0x20,
    984       CLICK_SRC_IA              = 0x40
    985       // 0x80 reserved
    986     } CLICK_SRC_BITS_T;
    987 
    988     /**
    989      * CLICK_THS bits
    990      *
    991      */
    992     typedef enum {
    993       CLICK_THS_THS0            = 0x01, // click threshold
    994       CLICK_THS_THS1            = 0x02,
    995       CLICK_THS_THS2            = 0x04,
    996       CLICK_THS_THS3            = 0x08,
    997       CLICK_THS_THS4            = 0x10,
    998       CLICK_THS_THS5            = 0x20,
    999       CLICK_THS_THS6            = 0x40,
   1000       _CLICK_THS_THS_MASK       = 127,
   1001       _CLICK_THS_THS_SHIFT      = 0
   1002       // 0x80 reserved
   1003     } CLICK_THS_BITS_T;
   1004 
   1005     /**
   1006      * CLICK_TIME_LIMIT bits
   1007      *
   1008      */
   1009     typedef enum {
   1010       CLICK_TIME_LIMIT_TLI0     = 0x01,
   1011       CLICK_TIME_LIMIT_TLI1     = 0x02,
   1012       CLICK_TIME_LIMIT_TLI2     = 0x04,
   1013       CLICK_TIME_LIMIT_TLI3     = 0x08,
   1014       CLICK_TIME_LIMIT_TLI4     = 0x10,
   1015       CLICK_TIME_LIMIT_TLI5     = 0x20,
   1016       CLICK_TIME_LIMIT_TLI6     = 0x40,
   1017       _CLICK_TIME_LIMIT_TLI_MASK = 127,
   1018       _CLICK_TIME_LIMIT_TLI_SHIFT = 0
   1019       // 0x80 reserved
   1020     } CLICK_TIME_LIMIT_BITS_T;
   1021 
   1022     /**
   1023      * ACT_THS (sleep-to-wake/return-to-sleep activation threshold) bits
   1024      *
   1025      */
   1026     typedef enum {
   1027       ACT_THS_ACTH0             = 0x01, // 1 LSb = 16mg (?)
   1028       ACT_THS_ACTH1             = 0x02,
   1029       ACT_THS_ACTH2             = 0x04,
   1030       ACT_THS_ACTH3             = 0x08,
   1031       ACT_THS_ACTH4             = 0x10,
   1032       ACT_THS_ACTH5             = 0x20,
   1033       ACT_THS_ACTH6             = 0x40,
   1034       _ACT_THS_ACTH_MASK        = 127,
   1035       _ACT_THS_ACTH_SHIFT       = 0
   1036       // 0x80 reserved
   1037     } ACT_THS_BITS_T;
   1038 
   1039     // Driver specific enumerations
   1040 
   1041     // device enums for read/write regs
   1042     typedef enum {
   1043       DEV_GYRO,
   1044       DEV_XM
   1045     } DEVICE_T;
   1046 
   1047     // interrupt selection for installISR() and uninstallISR()
   1048     typedef enum {
   1049       INTERRUPT_G_INT,  // gyroscope interrupt
   1050       INTERRUPT_G_DRDY, // gyroscope data ready interrupt
   1051       INTERRUPT_XM_GEN1, // XM interrupt generator 1
   1052       INTERRUPT_XM_GEN2  // XM interrupt generator 2
   1053     } INTERRUPT_PINS_T;
   1054 
   1055 
   1056     /**
   1057      * lsm9ds0 constructor
   1058      *
   1059      * @param bus i2c bus to use
   1060      * @param address the address for this device
   1061      */
   1062     LSM9DS0(int bus=LSM9DS0_I2C_BUS,
   1063             uint8_t gAddress=LSM9DS0_DEFAULT_GYRO_ADDR,
   1064             uint8_t xmAddress=LSM9DS0_DEFAULT_XM_ADDR);
   1065 
   1066     /**
   1067      * LSM9DS0 Destructor
   1068      */
   1069     ~LSM9DS0();
   1070 
   1071     /**
   1072      * set up initial values and start operation
   1073      *
   1074      * @return true if successful
   1075      */
   1076     bool init();
   1077 
   1078     /**
   1079      * update the accelerometer, gyroscope, magnetometer and
   1080      * termperature values.
   1081      */
   1082     void update();
   1083 
   1084     /**
   1085      * update the gyroscope values only
   1086      */
   1087     void updateGyroscope();
   1088 
   1089     /**
   1090      * update the accelerometer values only
   1091      */
   1092     void updateAccelerometer();
   1093 
   1094     /**
   1095      * update the magnetometer values only
   1096      */
   1097     void updateMagnetometer();
   1098 
   1099     /**
   1100      * update the temperature value only
   1101      */
   1102     void updateTemperature();
   1103 
   1104     /**
   1105      * read a register
   1106      *
   1107      * @param dev the device to access (XM or G)
   1108      * @param reg the register to read
   1109      * @return the value of the register
   1110      */
   1111     uint8_t readReg(DEVICE_T dev, uint8_t reg);
   1112 
   1113     /**
   1114      * read contiguous register into a buffer
   1115      *
   1116      * @param dev the device to access (XM or G)
   1117      * @param reg the register to start reading at
   1118      * @param buf the buffer to store the results
   1119      * @param len the number of registers to read
   1120      * @return the value of the register
   1121      */
   1122     void readRegs(DEVICE_T dev, uint8_t reg, uint8_t *buffer, int len);
   1123 
   1124     /**
   1125      * write to a register
   1126      *
   1127      * @param dev the device to access (XM or G)
   1128      * @param reg the register to write to
   1129      * @param val the value to write
   1130      * @return true if successful, false otherwise
   1131      */
   1132     bool writeReg(DEVICE_T dev, uint8_t reg, uint8_t val);
   1133 
   1134     /**
   1135      * enable or disable the gyro power down mode
   1136      *
   1137      * @param enable true to put device to sleep, false to wake up
   1138      * @return true if successful, false otherwise
   1139      */
   1140     bool setGyroscopePowerDown(bool enable);
   1141 
   1142     /**
   1143      * enable or disable gyroscope axes.  If all axis are disabled,
   1144      * and powerdown mode is not set, then the gyro goes into sleep
   1145      * mode.
   1146      *
   1147      * @param axes bit mask of valid axes, (CTRL_REG1_G_YEN, ...)
   1148      * @return true if successful, false otherwise
   1149      */
   1150     bool setGyroscopeEnableAxes(uint8_t axes);
   1151 
   1152     /**
   1153      * set the gyroscope Output Data Rate (ODR)
   1154      *
   1155      * @param odr one of the G_ODR_T values
   1156      * @return true if successful, false otherwise
   1157      */
   1158     bool setGyroscopeODR(G_ODR_T odr);
   1159 
   1160     /**
   1161      * set the scaling mode of the gyroscope
   1162      *
   1163      * @param scale one of the G_FS_T values
   1164      * @return true if successful, false otherwise
   1165      */
   1166     bool setGyroscopeScale(G_FS_T scale);
   1167 
   1168     /**
   1169      * enable or disable accelerometer axes.
   1170      *
   1171      * @param axes bit mask of valid axes, (CTRL_REG1_XM_AXEN, ...)
   1172      * @return true if successful, false otherwise
   1173      */
   1174     bool setAccelerometerEnableAxes(uint8_t axes);
   1175 
   1176     /**
   1177      * set the accelerometer Output Data Rate (ODR)
   1178      *
   1179      * @param odr one of the XM_AODR_T values
   1180      * @return true if successful, false otherwise
   1181      */
   1182     bool setAccelerometerODR(XM_AODR_T odr);
   1183 
   1184     /**
   1185      * set the scaling mode of the accelerometer
   1186      *
   1187      * @param scale one of the XM_AFS_T values
   1188      * @return true if successful, false otherwise
   1189      */
   1190     bool setAccelerometerScale(XM_AFS_T scale);
   1191 
   1192     /**
   1193      * set the magnetometer resolution
   1194      *
   1195      * @param res one of the XM_RES_T values
   1196      * @return true if successful, false otherwise
   1197      */
   1198     bool setMagnetometerResolution(XM_RES_T res);
   1199 
   1200     /**
   1201      * set the magnetometer Output Data Rate (ODR)
   1202      *
   1203      * @param odr one of the XM_ODR_T values
   1204      * @return true if successful, false otherwise
   1205      */
   1206     bool setMagnetometerODR(XM_ODR_T odr);
   1207 
   1208     /**
   1209      * set the magnetometer sensor mode
   1210      *
   1211      * @param mode one of the XM_MD_T values
   1212      * @return true if successful, false otherwise
   1213      */
   1214     bool setMagnetometerMode(XM_MD_T mode);
   1215 
   1216     /**
   1217      * enable or disable magnetometer low power mode (LPM).  When in
   1218      * low power mode, the magnetometer updates at 3.125Hz, regardless
   1219      * of it's ODR setting.
   1220      *
   1221      * @param enable true to enable LPM, false otherwise
   1222      * @return true if successful, false otherwise
   1223      */
   1224     bool setMagnetometerLPM(bool enable);
   1225 
   1226     /**
   1227      * set the scaling mode of the magnetometer
   1228      *
   1229      * @param scale one of the XM_MFS_T values
   1230      * @return true if successful, false otherwise
   1231      */
   1232     bool setMagnetometerScale(XM_MFS_T scale);
   1233 
   1234     /**
   1235      * get the accelerometer values in gravities
   1236      *
   1237      * @param x the returned x value, if arg is non-NULL
   1238      * @param y the returned y value, if arg is non-NULL
   1239      * @param z the returned z value, if arg is non-NULL
   1240      * @return true if successful, false otherwise
   1241      */
   1242     void getAccelerometer(float *x, float *y, float *z);
   1243 
   1244     /**
   1245      * get the gyroscope values in degrees per second
   1246      *
   1247      * @param x the returned x value, if arg is non-NULL
   1248      * @param y the returned y value, if arg is non-NULL
   1249      * @param z the returned z value, if arg is non-NULL
   1250      * @return true if successful, false otherwise
   1251      */
   1252     void getGyroscope(float *x, float *y, float *z);
   1253 
   1254     /**
   1255      * get the magnetometer values in gauss
   1256      *
   1257      * @param x the returned x value, if arg is non-NULL
   1258      * @param y the returned y value, if arg is non-NULL
   1259      * @param z the returned z value, if arg is non-NULL
   1260      * @return true if successful, false otherwise
   1261      */
   1262     void getMagnetometer(float *x, float *y, float *z);
   1263 
   1264 #if defined(SWIGJAVA) || defined(JAVACALLBACK)
   1265     /**
   1266      * get the accelerometer values in gravities
   1267      *
   1268      * @return Array containing X, Y, Z acceleration values
   1269      */
   1270     float *getAccelerometer();
   1271 
   1272     /**
   1273      * get the gyroscope values in degrees per second
   1274      *
   1275      * @return Array containing X, Y, Z gyroscope values
   1276      */
   1277     float *getGyroscope();
   1278 
   1279     /**
   1280      * get the magnetometer values in gauss
   1281      *
   1282      * @return Array containing X, Y, Z magnetometer values
   1283      */
   1284     float *getMagnetometer();
   1285 #endif
   1286 
   1287     /**
   1288      * get the temperature value.  Unfortunately the datasheet does
   1289      * not provide a mechanism to convert the temperature value into
   1290      * the correct value, so I made a 'guess'.  If it's wrong, and you
   1291      * figure it out, send a patch!
   1292      *
   1293      * @return the temperature value in degrees Celcius
   1294      */
   1295     float getTemperature();
   1296 
   1297     /**
   1298      * enable onboard temperature measurement sensor
   1299      *
   1300      * @param enable true to enable temperature sensor, false to disable
   1301      * @return true if successful, false otherwise
   1302      */
   1303     bool enableTemperatureSensor(bool enable);
   1304 
   1305     /**
   1306      * return the gyroscope status register
   1307      *
   1308      * @return bitmask of STATUS_REG_G_BITS_T bits
   1309      */
   1310     uint8_t getGyroscopeStatus();
   1311 
   1312     /**
   1313      * return the magnetometer status register
   1314      *
   1315      * @return bitmask of STATUS_REG_M_BITS_T bits
   1316      */
   1317     uint8_t getMagnetometerStatus();
   1318 
   1319     /**
   1320      * return the accelerometer status register
   1321      *
   1322      * @return bitmask of STATUS_REG_A_BITS_T bits
   1323      */
   1324     uint8_t getAccelerometerStatus();
   1325 
   1326     /**
   1327      * return the gyroscope interrupt config register
   1328      *
   1329      * @return bitmask of INT1_CFG_G_BITS_T bits
   1330      */
   1331     uint8_t getGyroscopeInterruptConfig();
   1332 
   1333     /**
   1334      * set the gyroscope interrupt config register
   1335      *
   1336      * @param enables bitmask of INT1_CFG_G_BITS_T values
   1337      * @return true if successful
   1338      */
   1339     bool setGyroscopeInterruptConfig(uint8_t enables);
   1340 
   1341     /**
   1342      * return the gyroscope interrupt src register
   1343      *
   1344      * @return bitmask of INT1_SRC_G_BITS_T bits
   1345      */
   1346     uint8_t getGyroscopeInterruptSrc();
   1347 
   1348     /**
   1349      * return the magnetometer interrupt control register
   1350      *
   1351      * @return bitmask of INT_CTRL_REG_M_BITS_T bits
   1352      */
   1353     uint8_t getMagnetometerInterruptControl();
   1354 
   1355     /**
   1356      * set the magnetometer interrupt control register
   1357      *
   1358      * @param enables bitmask of INT_CTRL_REG_M_BITS_T values
   1359      * @return true if successful
   1360      */
   1361     bool setMagnetometerInterruptControl(uint8_t enables);
   1362 
   1363     /**
   1364      * return the magnetometer interrupt src register
   1365      *
   1366      * @return bitmask of INT_SRC_REG_M_BITS_T bits
   1367      */
   1368     uint8_t getMagnetometerInterruptSrc();
   1369 
   1370     /**
   1371      * return the inertial interrupt generator 1 register
   1372      *
   1373      * @return bitmask of INT_GEN_X_REG_BITS_T bits
   1374      */
   1375     uint8_t getInterruptGen1();
   1376 
   1377     /**
   1378      * set the inertial interrupt generator 1 register
   1379      *
   1380      * @param enables bitmask of INT_GEN_X_REG_BITS_T values
   1381      * @return true if successful
   1382      */
   1383     bool setInterruptGen1(uint8_t enables);
   1384 
   1385     /**
   1386      * return the inertial interrupt generator 1 src register
   1387      *
   1388      * @return bitmask of INT_GEN_X_SRC_BITS_T bits
   1389      */
   1390     uint8_t getInterruptGen1Src();
   1391 
   1392     /**
   1393      * return the inertial interrupt generator 2 register
   1394      *
   1395      * @return bitmask of INT_GEN_X_REG_BITS_T bits
   1396      */
   1397     uint8_t getInterruptGen2();
   1398 
   1399     /**
   1400      * set the inertial interrupt generator 2 register
   1401      *
   1402      * @param enables bitmask of INT_GEN_X_REG_BITS_T values
   1403      * @return true if successful
   1404      */
   1405     bool setInterruptGen2(uint8_t enables);
   1406 
   1407     /**
   1408      * return the inertial interrupt generator 2 src register
   1409      *
   1410      * @return bitmask of INT_GEN_X_SRC_BITS_T bits
   1411      */
   1412     uint8_t getInterruptGen2Src();
   1413 
   1414 #if defined(SWIGJAVA) || defined(JAVACALLBACK)
   1415     void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
   1416 		    IsrCallback *cb);
   1417 #else
   1418     /**
   1419      * install an interrupt handler.
   1420      *
   1421      * @param intr one of the INTERRUPT_PINS_T values specifying which
   1422      * interrupt pin out of 4 you are installing
   1423      * @param gpio gpio pin to use as interrupt pin
   1424      * @param level the interrupt trigger level (one of mraa::Edge
   1425      * values).  Make sure that you have configured the interrupt pin
   1426      * properly for whatever level you choose.
   1427      * @param isr the interrupt handler, accepting a void * argument
   1428      * @param arg the argument to pass the the interrupt handler
   1429      */
   1430     void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
   1431                     void (*isr)(void *), void *arg);
   1432 #endif
   1433     /**
   1434      * uninstall a previously installed interrupt handler
   1435      *
   1436      * @param intr one of the INTERRUPT_PINS_T values specifying which
   1437      * interrupt pin out of 4 you are uninstalling
   1438      */
   1439     void uninstallISR(INTERRUPT_PINS_T intr);
   1440 
   1441   protected:
   1442     // uncompensated accelerometer and gyroscope values
   1443     float m_accelX;
   1444     float m_accelY;
   1445     float m_accelZ;
   1446 
   1447     float m_gyroX;
   1448     float m_gyroY;
   1449     float m_gyroZ;
   1450 
   1451     float m_magX;
   1452     float m_magY;
   1453     float m_magZ;
   1454 
   1455     // uncompensated temperature value
   1456     float m_temp;
   1457 
   1458     // accelerometer and gyro scaling factors, depending on their Full
   1459     // Scale settings.
   1460     float m_accelScale;
   1461     float m_gyroScale;
   1462     float m_magScale;
   1463 
   1464   private:
   1465     // OR'd with a register, this enables register autoincrement mode,
   1466     // which we need.
   1467 #if defined(SWIGJAVA) || defined(JAVACALLBACK)
   1468     void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level,
   1469                     void (*isr)(void *), void *arg);
   1470 #endif
   1471 
   1472     static const uint8_t m_autoIncrementMode = 0x80;
   1473 
   1474     mraa::I2c m_i2cG;
   1475     mraa::I2c m_i2cXM;
   1476     uint8_t m_gAddr;
   1477     uint8_t m_xmAddr;
   1478 
   1479     // return a reference to a gpio pin pointer depending on intr
   1480     mraa::Gpio*& getPin(INTERRUPT_PINS_T intr);
   1481 
   1482     // possible interrupt pins
   1483     mraa::Gpio *m_gpioG_INT;
   1484     mraa::Gpio *m_gpioG_DRDY;
   1485     mraa::Gpio *m_gpioXM_GEN1;
   1486     mraa::Gpio *m_gpioXM_GEN2;
   1487   };
   1488 }
   1489 
   1490 
   1491