1 /*
2  * Author: Jon Trulson <jtrulson@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