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 MPU60X0_I2C_BUS 0
37 #define MPU60X0_DEFAULT_I2C_ADDR 0x68
38 
39 namespace upm {
40 
41   /**
42    * @library mpu9150
43    * @sensor mpu60x0
44    * @comname MPU60X0 3-axis Gyroscope and 3-axis Accelerometer
45    * @type accelerometer compass
46    * @man seeed
47    * @con i2c gpio
48    *
49    * @brief API for the MPU60X0 3-axis Gyroscope and 3-axis Accelerometer
50    *
51    * The MPU60X0 devices provide the world’s first integrated 6-axis
52    * motion processor solution that eliminates the package-level
53    * gyroscope and accelerometer cross-axis misalignment associated
54    * with discrete solutions. The devices combine a 3-axis gyroscope
55    * and a 3-axis accelerometer on the same silicon die.
56    *
57    * While not all of the functionality of this device is supported
58    * initially, methods and register definitions are provided that
59    * should allow an end user to implement whatever features are
60    * required.
61    *
62    * @snippet mpu60x0.cxx Interesting
63    */
64   class MPU60X0 {
65   public:
66 
67     // NOTE: These enums were composed from both the mpu6050 and
68     // mpu9150 register maps, since this driver was written using an
69     // mpu9150, but we'd like this module to be usable with a
70     // standalone mpu60x0.
71     //
72     // Registers and bitfields marked with an '*' in their
73     // comment indicate registers or bit fields present in the mpu9150
74     // register map, but not in the original mpu6050 register map.  If
75     // using this module on a standalone mpu6050, you should avoid
76     // using those registers or bitfields marked with an *.
77 
78     /**
79      * MPU60X0 registers
80      */
81     typedef enum {
82       REG_SELF_TEST_X           = 0x0d,
83       REG_SELF_TEST_Y           = 0x0e,
84       REG_SELF_TEST_Z           = 0x0f,
85       REG_SELF_TEST_A           = 0x10,
86 
87       REG_SMPLRT_DIV            = 0x19, // sample rate divider
88 
89       REG_CONFIG                = 0x1a,
90       REG_GYRO_CONFIG           = 0x1b,
91       REG_ACCEL_CONFIG          = 0x1c,
92 
93       REG_FF_THR                = 0x1d, // *freefall threshold
94       REG_FF_DUR                = 0x1e, // *freefall duration
95 
96       REG_MOT_THR               = 0x1f, // motion threshold
97       REG_MOT_DUR               = 0x20, // *motion duration
98 
99       REG_ZRMOT_THR             = 0x21, // *zero motion threshhold
100       REG_ZRMOT_DUR             = 0x22, // *zero motion duration
101 
102       REG_FIFO_EN               = 0x23,
103 
104       REG_I2C_MST_CTRL          = 0x24, // I2C master control
105 
106       REG_I2C_SLV0_ADDR         = 0x25, // I2C slave 0
107       REG_I2C_SLV0_REG          = 0x26,
108       REG_I2C_SLV0_CTRL         = 0x27,
109 
110       REG_I2C_SLV1_ADDR         = 0x28, // I2C slave 1
111       REG_I2C_SLV1_REG          = 0x29,
112       REG_I2C_SLV1_CTRL         = 0x2a,
113 
114       REG_I2C_SLV2_ADDR         = 0x2b, // I2C slave 2
115       REG_I2C_SLV2_REG          = 0x2c,
116       REG_I2C_SLV2_CTRL         = 0x2d,
117 
118       REG_I2C_SLV3_ADDR         = 0x2e, // I2C slave 3
119       REG_I2C_SLV3_REG          = 0x2f,
120       REG_I2C_SLV3_CTRL         = 0x30,
121 
122       REG_I2C_SLV4_ADDR         = 0x31, // I2C slave 4
123       REG_I2C_SLV4_REG          = 0x32,
124       REG_I2C_SLV4_DO           = 0x33,
125       REG_I2C_SLV4_CTRL         = 0x34,
126       REG_I2C_SLV4_DI           = 0x35,
127 
128       REG_I2C_MST_STATUS        = 0x36, // I2C master status
129 
130       REG_INT_PIN_CFG           = 0x37, // interrupt pin config/i2c bypass
131       REG_INT_ENABLE            = 0x38,
132 
133       // 0x39 reserved
134 
135       REG_INT_STATUS            = 0x3a, // interrupt status
136 
137       REG_ACCEL_XOUT_H          = 0x3b, // accelerometer outputs
138       REG_ACCEL_XOUT_L          = 0x3c,
139 
140       REG_ACCEL_YOUT_H          = 0x3d,
141       REG_ACCEL_YOUT_L          = 0x3e,
142 
143       REG_ACCEL_ZOUT_H          = 0x3f,
144       REG_ACCEL_ZOUT_L          = 0x40,
145 
146       REG_TEMP_OUT_H            = 0x41, // temperature output
147       REG_TEMP_OUT_L            = 0x42,
148 
149       REG_GYRO_XOUT_H           = 0x43, // gyro outputs
150       REG_GYRO_XOUT_L           = 0x44,
151 
152       REG_GYRO_YOUT_H           = 0x45,
153       REG_GYRO_YOUT_L           = 0x46,
154 
155       REG_GYRO_ZOUT_H           = 0x47,
156       REG_GYRO_ZOUT_L           = 0x48,
157 
158       REG_EXT_SENS_DATA_00      = 0x49, // external sensor data
159       REG_EXT_SENS_DATA_01      = 0x4a,
160       REG_EXT_SENS_DATA_02      = 0x4b,
161       REG_EXT_SENS_DATA_03      = 0x4c,
162       REG_EXT_SENS_DATA_04      = 0x4d,
163       REG_EXT_SENS_DATA_05      = 0x4e,
164       REG_EXT_SENS_DATA_06      = 0x4f,
165       REG_EXT_SENS_DATA_07      = 0x50,
166       REG_EXT_SENS_DATA_08      = 0x51,
167       REG_EXT_SENS_DATA_09      = 0x52,
168       REG_EXT_SENS_DATA_10      = 0x53,
169       REG_EXT_SENS_DATA_11      = 0x54,
170       REG_EXT_SENS_DATA_12      = 0x55,
171       REG_EXT_SENS_DATA_13      = 0x56,
172       REG_EXT_SENS_DATA_14      = 0x57,
173       REG_EXT_SENS_DATA_15      = 0x58,
174       REG_EXT_SENS_DATA_16      = 0x59,
175       REG_EXT_SENS_DATA_17      = 0x5a,
176       REG_EXT_SENS_DATA_18      = 0x5b,
177       REG_EXT_SENS_DATA_19      = 0x5c,
178       REG_EXT_SENS_DATA_20      = 0x5d,
179       REG_EXT_SENS_DATA_21      = 0x5e,
180       REG_EXT_SENS_DATA_22      = 0x5f,
181       REG_EXT_SENS_DATA_23      = 0x60,
182 
183       REG_MOT_DETECT_STATUS     = 0x61, // *
184 
185       // 0x62 reserved
186 
187       REG_I2C_SLV0_DO           = 0x63, // I2C slave data outs
188       REG_I2C_SLV1_DO           = 0x64,
189       REG_I2C_SLV2_DO           = 0x65,
190       REG_I2C_SLV3_DO           = 0x66,
191 
192       REG_I2C_MST_DELAY_CTRL    = 0x67,
193 
194       REG_SIGNAL_PATH_RESET     = 0x68, // signal path resets
195 
196       REG_MOT_DETECT_CTRL       = 0x69,
197 
198       REG_USER_CTRL             = 0x6a,
199 
200       REG_PWR_MGMT_1            = 0x6b, // power management
201       REG_PWR_MGMT_2            = 0x6c,
202 
203       // 0x6d-0x71 reserved
204 
205       REG_FIFO_COUNTH           = 0x72,
206       REG_FIFO_COUNTL           = 0x73,
207 
208       REG_FIFO_R_W              = 0x74,
209 
210       REG_WHO_AM_I              = 0x75
211     } MPU60X0_REG_T;
212 
213     /**
214      * CONFIG bits
215      */
216     typedef enum {
217       CONFIG_DLPF_CFG0            = 0x01, // digital low-pass filter config
218       CONFIG_DLPF_CFG1            = 0x02,
219       CONFIG_DLPF_CFG2            = 0x04,
220       _CONFIG_DLPF_SHIFT          = 0,
221       _CONFIG_DLPF_MASK           = 7,
222 
223       CONFIG_EXT_SYNC_SET0        = 0x08, // FSYNC pin config
224       CONFIG_EXT_SYNC_SET1        = 0x10,
225       CONFIG_EXT_SYNC_SET2        = 0x20,
226       _CONFIG_EXT_SYNC_SET_SHIFT  = 3,
227       _CONFIG_EXT_SYNC_SET_MASK   = 7
228     } CONFIG_BITS_T;
229 
230     /**
231      * CONFIG DLPF_CFG values
232      */
233     typedef enum {
234       DLPF_260_256                = 0, // accel/gyro bandwidth (Hz)
235       DLPF_184_188                = 1,
236       DLPF_94_98                  = 2,
237       DLPF_44_42                  = 3,
238       DLPF_21_20                  = 4,
239       DLPF_10_10                  = 5,
240       DLPF_5_5                    = 6,
241       DLPF_RESERVED               = 7
242     } DLPF_CFG_T;
243 
244     /**
245      * CONFIG EXT_SYNC_SET values
246      */
247     typedef enum {
248       EXT_SYNC_DISABLED           = 0,
249       EXT_SYNC_TEMP_OUT           = 1,
250       EXT_SYNC_GYRO_XOUT          = 2,
251       EXT_SYNC_GYRO_YOUT          = 3,
252       EXT_SYNC_GYRO_ZOUT          = 4,
253       EXT_SYNC_ACCEL_XOUT         = 5,
254       EXT_SYNC_ACCEL_YOUT         = 6,
255       EXT_SYNC_ACCEL_ZOUT         = 7
256     } EXT_SYNC_SET_T;
257 
258     /**
259      * GYRO_CONFIG bits
260      */
261     typedef enum {
262       // 0x01-0x04 reserved
263       FS_SEL0                          = 0x08, // gyro full scale range
264       FS_SEL1                          = 0x10,
265       _FS_SEL_SHIFT                    = 3,
266       _FS_SEL_MASK                     = 3,
267 
268       ZG_ST                            = 0x20, // gyro self test bits
269       YG_ST                            = 0x40,
270       XG_ST                            = 0x80
271     } GRYO_CONFIG_BITS_T;
272 
273     /**
274      * GYRO FS_SEL values
275      */
276     typedef enum {
277       FS_250                           = 0, // 250 deg/s, 131 LSB deg/s
278       FS_500                           = 1, // 500 deg/s, 65.5 LSB deg/s
279       FS_1000                          = 2, // 1000 deg/s, 32.8 LSB deg/s
280       FS_2000                          = 3  // 2000 deg/s, 16.4 LSB deg/s
281     } FS_SEL_T;
282 
283     /**
284      * ACCEL_CONFIG bits
285      */
286     typedef enum {
287       // 0x01-0x04 reserved
288       AFS_SEL0                         = 0x08, // accel full scale range
289       AFS_SEL1                         = 0x10,
290       _AFS_SEL_SHIFT                   = 3,
291       _AFS_SEL_MASK                    = 3,
292 
293       ZA_ST                            = 0x20, // gyro self test bits
294       YA_ST                            = 0x40,
295       XA_ST                            = 0x80
296     } ACCEL_CONFIG_BITS_T;
297 
298     /**
299      * ACCEL AFS_SEL (full scaling) values
300      */
301     typedef enum {
302       AFS_2                            = 0, // 2g, 16384 LSB/g
303       AFS_4                            = 1, // 4g, 8192 LSB/g
304       AFS_8                            = 2, // 8g, 4096 LSB/g
305       AFS_16                           = 3  // 16g, 2048 LSB/g
306     } AFS_SEL_T;
307 
308     /**
309      * REG_FIFO_EN bits
310      */
311     typedef enum {
312       SLV0_FIFO_EN                     = 0x01,
313       SLV1_FIFO_EN                     = 0x02,
314       SLV2_FIFO_EN                     = 0x04,
315 
316       ACCEL_FIFO_EN                    = 0x08,
317 
318       ZG_FIFO_EN                       = 0x10,
319       YG_FIFO_EN                       = 0x20,
320       XG_FIFO_EN                       = 0x40,
321 
322       TEMP_FIFO_EN                     = 0x80
323     } FIFO_EN_BITS_T;
324 
325     /**
326      * REG_I2C_MST_CTRL bits
327      */
328     typedef enum {
329       I2C_MST_CLK0                     = 0x01,
330       I2C_MST_CLK1                     = 0x02,
331       I2C_MST_CLK2                     = 0x04,
332       I2C_MST_CLK3                     = 0x08,
333       _I2C_MST_CLK_SHIFT               = 0,
334       _I2C_MST_CLK_MASK                = 15,
335 
336       I2C_MST_P_NSR                    = 0x10,
337 
338       SLV_3_FIFO_EN                    = 0x20,
339 
340       WAIT_FOR_ES                      = 0x40,
341 
342       MULT_MST_EN                      = 0x80
343     } I2C_MST_CTRL_BITS_T;
344 
345     /**
346      * I2C_MST_CLK values
347      */
348     typedef enum {
349       MST_CLK_348                      = 0, // 348Khz
350       MST_CLK_333                      = 1,
351       MST_CLK_320                      = 2,
352       MST_CLK_308                      = 3,
353       MST_CLK_296                      = 4,
354       MST_CLK_286                      = 5,
355       MST_CLK_276                      = 6,
356       MST_CLK_267                      = 7,
357       MST_CLK_258                      = 8,
358       MST_CLK_500                      = 9,
359       MST_CLK_471                      = 10,
360       MST_CLK_444                      = 11,
361       MST_CLK_421                      = 12,
362       MST_CLK_400                      = 13,
363       MST_CLK_381                      = 14,
364       MST_CLK_364                      = 15
365     } I2C_MST_CLK_T;
366 
367     /**
368      * REG_I2C SLV0-SLV4 _ADDR bits
369      */
370     typedef enum {
371       I2C_SLV_ADDR0                    = 0x01,
372       I2C_SLV_ADDR1                    = 0x02,
373       I2C_SLV_ADDR2                    = 0x04,
374       I2C_SLV_ADDR3                    = 0x08,
375       I2C_SLV_ADDR4                    = 0x10,
376       I2C_SLV_ADDR5                    = 0x20,
377       I2C_SLV_ADDR6                    = 0x40,
378       _I2C_SLV_ADDR_SHIFT              = 0,
379       _I2C_SLV_ADDR_MASK               = 127,
380 
381       I2C_SLV_RW                       = 0x80
382     } I2C_SLV_ADDR_BITS_T;
383 
384     /**
385      * REG_I2C SLV0-SLV3 _CTRL bits
386      */
387     typedef enum {
388       I2C_SLV_LEN0                     = 0x01,
389       I2C_SLV_LEN1                     = 0x02,
390       I2C_SLV_LEN2                     = 0x04,
391       I2C_SLV_LEN3                     = 0x08,
392       _I2C_SLV_LEN_SHIFT               = 0,
393       _I2C_SLV_LEN_MASK                = 15,
394 
395       I2C_SLV_GRP                      = 0x10,
396       I2C_SLV_REG_DIS                  = 0x20,
397       I2C_SLV_BYTE_SW                  = 0x40,
398       I2C_SLV_EN                       = 0x80
399     } I2C_SLV_CTRL_BITS_T;
400 
401     /**
402      * REG_I2C_SLV4_CTRL bits, these are different from the SLV0-SLV3
403      * CRTL bits.
404      *
405      * MST_DLY is not enumerated in the register map.  It configures
406      * the reduced access rate of i2c slaves relative to the sample
407      * rate. When a slave’s access rate is decreased relative to the
408      * Sample Rate, the slave is accessed every
409      * 1 / (1 + I2C_MST_DLY) samples
410      */
411     typedef enum {
412       I2C_MST_DLY0                     = 0x01,
413       I2C_MST_DLY1                     = 0x02,
414       I2C_MST_DLY2                     = 0x04,
415       I2C_MST_DLY3                     = 0x08,
416       I2C_MST_DLY4                     = 0x10,
417       _I2C_MST_DLY_SHIFT               = 0,
418       _I2C_MST_DLY_MASK                = 31,
419 
420       I2C_SLV4_REG_DIS                 = 0x20,
421       I2C_SLV4_INT_EN                  = 0x40,
422       I2C_SLV4_EN                      = 0x80
423     } I2C_SLV4_CTRL_BITS_T;
424 
425     /**
426      * REG_I2C_MST_STATUS bits
427      */
428     typedef enum {
429       I2C_SLV0_NACK                    = 0x01,
430       I2C_SLV1_NACK                    = 0x02,
431       I2C_SLV2_NACK                    = 0x04,
432       I2C_SLV3_NACK                    = 0x08,
433       I2C_SLV4_NACK                    = 0x10,
434 
435       I2C_LOST_ARB                     = 0x20,
436       I2C_SLV4_DONE                    = 0x40,
437       PASS_THROUGH                     = 0x80
438     } I2C_MST_STATUS_BITS_T;
439 
440     /**
441      * REG_INT_PIN_CFG bits
442      */
443     typedef enum {
444       CLKOUT_EN                        = 0x01, // *
445 
446       I2C_BYPASS_ENABLE                = 0x02,
447 
448       FSYNC_INT_EN                     = 0x04,
449       FSYNC_INT_LEVEL                  = 0x08,
450 
451       INT_RD_CLEAR                     = 0x10,
452 
453       LATCH_INT_EN                     = 0x20,
454 
455       INT_OPEN                         = 0x40,
456       INT_LEVEL                        = 0x80
457     } INT_PIN_CFG_BITS_T;
458 
459     /**
460      * REG_INT_ENABLE bits
461      */
462     typedef enum {
463       DATA_RDY_EN                      = 0x01, // *
464 
465       // 0x02, 0x04 reserved
466 
467       I2C_MST_INT_EN                   = 0x08,
468 
469       FIFO_OFLOW_EN                    = 0x10,
470 
471       ZMOT_EN                          = 0x20, // *zero motion
472       MOT_EN                           = 0x40,
473       FF_EN                            = 0x80  // *freefall
474     } INT_ENABLE_BITS_T;
475 
476     /**
477      * REG_INT_STATUS bits
478      */
479     typedef enum {
480       DATA_RDY_INT                     = 0x01,
481 
482       // 0x02, 0x04 reserved
483 
484       I2C_MST_INT                      = 0x08,
485 
486       FIFO_OFLOW_INT                   = 0x10,
487 
488       ZMOT_INT                         = 0x20, // *zero motion
489       MOT_INT                          = 0x40,
490       FF_INT                           = 0x80  // *freefall
491     } INT_STATUS_BITS_T;
492 
493     /**
494      * REG_MOT_DETECT_STATUS bits (mpu9150 only)
495      */
496     typedef enum {
497       MOT_ZRMOT                        = 0x01, // *
498 
499       // 0x02 reserved
500 
501       MOT_ZPOS                         = 0x04, // *
502       MOT_ZNEG                         = 0x08, // *
503 
504       MOT_YPOS                         = 0x10, // *
505       MOT_YNEG                         = 0x20, // *
506 
507       MOT_XPOS                         = 0x40, // *
508       MOT_XNEG                         = 0x80, // *
509     } MOT_DETECT_STATUS_BITS_T;
510 
511     /**
512      * REG_MST_DELAY_CTRL bits
513      */
514     typedef enum {
515       I2C_SLV0_DLY_EN                  = 0x01,
516       I2C_SLV1_DLY_EN                  = 0x02,
517       I2C_SLV2_DLY_EN                  = 0x04,
518       I2C_SLV3_DLY_EN                  = 0x08,
519       I2C_SLV4_DLY_EN                  = 0x10,
520 
521       // 0x20, 0x40, reserved
522 
523       DELAY_ES_SHADOW                  = 0x80
524     } MST_DELAY_CTRL_BITS_T;
525 
526     /**
527      * REG_SIGNAL_PATH_RESET bits
528      */
529     typedef enum {
530       TEMP_RESET                       = 0x01,
531       ACCEL_RESET                      = 0x02,
532       GYRO_RESET                       = 0x04
533 
534       // 0x08-0x80 reserved
535     } SIGNAL_PATH_RESET_BITS_T;
536 
537     /**
538      * REG_MOT_DETECT_CTRL bits
539      */
540     typedef enum {
541       MOT_COUNT0                       = 0x01, // *
542       MOT_COUNT1                       = 0x02, // *
543       _MOT_COUNT_SHIFT                 = 0,
544       _MOT_COUNT_MASK                  = 3,
545 
546       FF_COUNT0                        = 0x04, // *
547       FF_COUNT1                        = 0x08, // *
548       _FF_COUNT_SHIFT                  = 2,
549       _FF_COUNT_MASK                   = 3,
550 
551       ACCEL_ON_DELAY0                  = 0x10,
552       ACCEL_ON_DELAY1                  = 0x20,
553       _ACCEL_ON_DELAY_SHIFT            = 4,
554       _ACCEL_ON_DELAY_MASK             = 3
555       // 0x40,0x80 reserved
556     } MOT_DETECT_CTRL_BITS_T;
557 
558     /**
559      * MOT_COUNT or FF_COUNT values (mpu9150 only)
560      */
561     typedef enum {
562       COUNT_0                          = 0, // Reset
563       COUNT_1                          = 1, // counter decrement 1
564       COUNT_2                          = 2, // counter decrement 2
565       COUNT_4                          = 3  // counter decrement 4
566     } MOT_FF_COUNT_T;
567 
568     /**
569      * ACCEL_ON_DELAY values
570      */
571     typedef enum {
572       ON_DELAY_0                       = 0, // no delay
573       ON_DELAY_1                       = 1, // add 1ms
574       ON_DELAY_2                       = 2, // add 2ms
575       ON_DELAY_3                       = 3  // add 3ms
576     } ACCEL_ON_DELAY_T;
577 
578     /**
579      * REG_USER_CTRL bits
580      */
581     typedef enum {
582       SIG_COND_RESET                   = 0x01,
583       I2C_MST_RESET                    = 0x02,
584       FIFO_RESET                       = 0x04,
585 
586       // 0x08 reserved
587 
588       I2C_IF_DIS                       = 0x10,
589       I2C_MST_EN                       = 0x20,
590       FIFO_EN                          = 0x40
591 
592       /// 0x80 reserved
593     } USER_CTRL_BITS_T;
594 
595     /**
596      * REG_PWR_MGMT_1 bits
597      */
598     typedef enum {
599       CLKSEL0                          = 0x01,
600       CLKSEL1                          = 0x02,
601       CLKSEL2                          = 0x04,
602       _CLKSEL_SHIFT                    = 0,
603       _CLKSEL_MASK                     = 7,
604 
605       TEMP_DIS                         = 0x08,
606 
607       // 0x10 reserved
608 
609       PWR_CYCLE                        = 0x20,
610       PWR_SLEEP                        = 0x40,
611       DEVICE_RESET                     = 0x80
612     } PWR_MGMT_1_BITS_T;
613 
614     /**
615      * CLKSEL values
616      */
617     typedef enum {
618       INT_8MHZ                         = 0, // internal 8Mhz osc
619       PLL_XG                           = 1, // PLL X axis gyro
620       PLL_YG                           = 2, // PLL Y axis gyro
621       PLL_ZG                           = 3, // PLL Z axis gyro
622       PLL_EXT_32KHZ                    = 4, // PLL with external 32.768Khz ref
623       PLL_EXT_19MHZ                    = 5, // PLL with external 19.2Mhz ref
624       // 6 - reserved
625       CLK_STOP                         = 7  // stops clk
626     } CLKSEL_T;
627 
628     /**
629      * REG_PWR_MGMT_2 bits
630      */
631     typedef enum {
632       STBY_ZG                          = 0x01,
633       STBY_YG                          = 0x02,
634       STBY_XG                          = 0x04,
635       STBY_ZA                          = 0x08,
636       STBY_YA                          = 0x10,
637       STBY_XA                          = 0x20,
638 
639       LP_WAKE_CTRL0                    = 0x40,
640       LP_WAKE_CTRL1                    = 0x80,
641       _LP_WAKE_CTRL_SHIFT              = 6,
642       _LP_WAKE_CTRL_MASK               = 3
643     } PWR_MGMT_2_BITS_T;
644 
645     /**
646      * LP_WAKE_CTRL values
647      */
648     typedef enum {
649       LP_WAKE_1_25                     = 0, // wakeup feq: 1.25hz
650       LP_WAKE_5                        = 1, // 5hz
651       LP_WAKE_20                       = 2, // 20hz
652       LP_WAKE_40                       = 3, // 40hz
653     } LP_WAKE_CRTL_T;
654 
655 
656     /**
657      * mpu60x0 constructor
658      *
659      * @param bus i2c bus to use
660      * @param address the address for this device
661      */
662     MPU60X0(int bus=MPU60X0_I2C_BUS, uint8_t address=MPU60X0_DEFAULT_I2C_ADDR);
663 
664     /**
665      * MPU60X0 Destructor
666      */
667     ~MPU60X0();
668 
669     /**
670      * set up initial values and start operation
671      *
672      * @return true if successful
673      */
674     bool init();
675 
676     /**
677      * take a measurement and store the current sensor values
678      * internally.  Note, these user facing registers are only updated
679      * from the internal device sensor values when the i2c serial
680      * traffic is 'idle'.  So, if you are reading the values too fast,
681      * the bus may never be idle, and you will just end up reading
682      * the same values over and over.
683      *
684      * Unfortunately, it is is not clear how long 'idle' actually
685      * means, so if you see this behavior, reduce the rate at which
686      * you are calling update().
687      *
688      */
689     void update();
690 
691     /**
692      * read a register
693      *
694      * @param reg the register to read
695      * @return the value of the register
696      */
697     uint8_t readReg(uint8_t reg);
698 
699     /**
700      * read contiguous refister into a buffer
701      *
702      * @param reg the register to start reading at
703      * @param buffer the buffer to store the results
704      * @param len the number of registers to read
705      * @return the value of the register
706      */
707     void readRegs(uint8_t reg, uint8_t *buffer, int len);
708 
709     /**
710      * write to a register
711      *
712      * @param reg the register to write to
713      * @param val the value to write
714      * @return true if successful, false otherwise
715      */
716     bool writeReg(uint8_t reg, uint8_t val);
717 
718     /**
719      * enable or disable device sleep
720      *
721      * @param enable true to put device to sleep, false to wake up
722      * @return true if successful, false otherwise
723      */
724     bool setSleep(bool enable);
725 
726     /**
727      * specify the clock source for the device to use
728      *
729      * @param clk one of the CLKSEL_T values
730      * @return true if successful, false otherwise
731      */
732     bool setClockSource(CLKSEL_T clk);
733 
734     /**
735      * set the scaling mode of the gyroscope
736      *
737      * @param scale one of the FS_SEL_T values
738      * @return true if successful, false otherwise
739      */
740     bool setGyroscopeScale(FS_SEL_T scale);
741 
742     /**
743      * set the scaling mode of the accelerometer
744      *
745      * @param scale one of the AFS_SEL_T values
746      * @return true if successful, false otherwise
747      */
748     bool setAccelerometerScale(AFS_SEL_T scale);
749 
750     /**
751      * set the Low Pass Digital filter.  This enables filtering (if
752      * non-0) of the accelerometer and gyro outputs.
753      *
754      * @param scale one of the DLPF_CFG_T values
755      * @return true if successful, false otherwise
756      */
757     bool setDigitalLowPassFilter(DLPF_CFG_T dlp);
758 
759     /**
760      * set the sample rate divider.  This register specifies the
761      * divider from the gyro output rate used to generate the Sample
762      * Rate.  The sensor registor output, FIFO output, DMP sampling
763      * and motion detection are all based on the Sample Rate.
764      *
765      * The Sample Rate is generated by dividing the gyro output rate
766      * by this register:
767      *
768      * Sample Rate = Gyro output rate / (1 + sample rate divider).
769      *
770      * The Gyro output rate is 8Khz when the Digital Low Pass Filter
771      * (DLPF) is 0 or 7 (DLPF_260_256 or DLPF_RESERVED), and 1Khz
772      * otherwise.
773      *
774      * @param scale one of the DLPF_CFG_T values
775      * @return true if successful, false otherwise
776      */
777     bool setSampleRateDivider(uint8_t div);
778 
779     /**
780      * get the current Sample Rate divider
781      *
782      * @return the current sample rate divider
783      */
784     uint8_t getSampleRateDivider();
785 
786     /**
787      * get the accelerometer values
788      *
789      * @param x the returned x value, if arg is non-NULL
790      * @param y the returned y value, if arg is non-NULL
791      * @param z the returned z value, if arg is non-NULL
792      * @return true if successful, false otherwise
793      */
794     void getAccelerometer(float *x, float *y, float *z);
795 
796     /**
797      * get the gyroscope values
798      *
799      * @param x the returned x value, if arg is non-NULL
800      * @param y the returned y value, if arg is non-NULL
801      * @param z the returned z value, if arg is non-NULL
802      * @return true if successful, false otherwise
803      */
804     void getGyroscope(float *x, float *y, float *z);
805 
806 #if defined(SWIGJAVA) || defined(JAVACALLBACK)
807     /**
808      * get the accelerometer values
809      *
810      * @return Array containing X, Y, Z accelerometer values
811      */
812     float *getAccelerometer();
813 
814     /**
815      * get the gyroscope values
816      *
817      * @return Array containing X, Y, Z gyroscope values
818      */
819     float *getGyroscope();
820 #endif
821 
822 
823     /**
824      * get the temperature value
825      *
826      * @return the temperature value in degrees Celcius
827      */
828     virtual float getTemperature();
829 
830     /**
831      * enable onboard temperature measurement sensor
832      *
833      * @param enable true to enable temperature sensor, false to disable
834      * @return true if successful, false otherwise
835      */
836     bool enableTemperatureSensor(bool enable);
837 
838     /**
839      * configure external sync.  An external signal connected to the
840      * FSYNC pin can be sampled by configuring EXT_SYNC_SET.  Signal
841      * changes to the FSYNC pin are latched so that short strobes may
842      * be captured. The latched FSYNC signal will be sampled at the
843      * Sampling Rate, as defined in register 25. After sampling, the
844      * latch will reset to the current FSYNC signal state.
845      *
846      * The sampled value will be reported in place of the least
847      * significant bit in a sensor data register determined by the
848      * value of EXT_SYNC_SET
849      *
850      * @param val one of the EXT_SYNC_SET_T values
851      * @return true if successful, false otherwise
852      */
853     bool setExternalSync(EXT_SYNC_SET_T val);
854 
855     /**
856      * enable I2C Bypass.  Enabling this feature allows devices on the
857      * MPU60X0 auxillary I2C bus to be visible on the MCU's I2C bus.
858      *
859      * @param enable true to I2C bypass
860      * @return true if successful, false otherwise
861      */
862     bool enableI2CBypass(bool enable);
863 
864     /**
865      * set the motion detection threshold for interrupt generation.
866      * Motion is detected when the absolute value of any of the
867      * accelerometer measurements exceeds this Motion detection
868      * threshold.
869      *
870      * @param thr threshold
871      * @return true if successful, false otherwise
872      */
873     bool setMotionDetectionThreshold(uint8_t thr);
874 
875     /**
876      * return the interrupt status register.
877      *
878      * @return the interrupt status word (see INT_STATUS_BITS_T)
879      */
880     uint8_t getInterruptStatus();
881 
882     /**
883      * set the interrupt enables
884      *
885      * @param enables bitmask of INT_ENABLE_BITS_T values to enable
886      * @return true if successful, false otherwise
887      */
888     bool setInterruptEnables(uint8_t enables);
889 
890     /**
891      * get the current interrupt enables register
892      *
893      * @return bitmask of INT_ENABLE_BITS_T values
894      */
895     uint8_t getInterruptEnables();
896 
897     /**
898      * set the interrupt pin configuration
899      *
900      * @param cfg bitmask of INT_PIN_CFG_BITS_T values
901      * @return true if successful, false otherwise
902      */
903     bool setInterruptPinConfig(uint8_t cfg);
904 
905     /**
906      * get the current interrupt pin configuration
907      *
908      * @return bitmask of INT_PIN_CFG_BITS_T values
909      */
910     uint8_t getInterruptPinConfig();
911 
912     /**
913      * install an interrupt handler.
914      *
915      * @param gpio gpio pin to use as interrupt pin
916      * @param level the interrupt trigger level (one of mraa::Edge
917      * values).  Make sure that you have configured the interrupt pin
918      * (setInterruptPinConfig()) properly for whatever level you
919      * choose.
920      * @param isr the interrupt handler, accepting a void * argument
921      * @param arg the argument to pass the the interrupt handler
922      */
923 #if defined(SWIGJAVA) || defined(JAVACALLBACK)
924     void installISR(int gpio, mraa::Edge level, IsrCallback *cb);
925 #else
926     void installISR(int gpio, mraa::Edge level, void (*isr)(void *), void *arg);
927 #endif
928 
929     /**
930      * uninstall a previously installed interrupt handler
931      *
932      */
933     void uninstallISR();
934 
935   protected:
936     // uncompensated accelerometer and gyroscope values
937     float m_accelX;
938     float m_accelY;
939     float m_accelZ;
940 
941     float m_gyroX;
942     float m_gyroY;
943     float m_gyroZ;
944 
945     // uncompensated temperature value
946     float m_temp;
947 
948     // accelerometer and gyro scaling factors, depending on their Full
949     // Scale settings.
950     float m_accelScale;
951     float m_gyroScale;
952 
953   private:
954 #if defined(SWIGJAVA) || defined(JAVACALLBACK)
955     void installISR(int gpio, mraa::Edge level, void (*isr)(void *), void *arg);
956 #endif
957 
958     mraa::I2c m_i2c;
959     uint8_t m_addr;
960 
961     mraa::Gpio *m_gpioIRQ;
962   };
963 }
964 
965 
966