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
39namespace 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