Felix Rüdiger / MPU6050_lib

Dependents:   BLE_Nano_MPU6050Service

MPU6050.h

Committer:
fruediger
Date:
2015-07-13
Revision:
2:32b13cc64cb0
Parent:
1:96a227d1ca7e
Child:
3:a6e53ab2c8c0

File content as of revision 2:32b13cc64cb0:

#pragma once
#ifndef __MPU6050_H__
#define __MPU6050_H__

/**
 * Based on the work of authors of
 * https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050
 * 
 * Ported by Felix Rüdiger, 2015
 * (scrapping all the I2C-slave-bus stuff)
 *
 */
 
#include "mbed.h"
#include "helpers.h"

typedef struct 
{
    int16_t ax, ay, az;
    int16_t temp;
    int16_t ox, oy, oz;
} MPU6050SensorReading;

class MPU6050
{
    public:
        /**
         * Constants
         */  
    
        enum BaseAddress
        {
                                                    // left shift by 1 bit is neccessary for mbed's I2C abstraction class
                                                    // look at https://developer.mbed.org/users/okano/notebook/i2c-access-examples/
            ADDRESS_0                               = BYTE(01101000) << 1,
            ADRESSS_1                               = BYTE(01101001) << 1
        };
        
        enum Register
        {
            REG_AUX_VDDIO                           = 0x01, // R/W
            REG_SMPLRT_DIV                          = 0x19, // R/W
            REG_CONFIG                              = 0x1A, // R/W
            REG_GYRO_CONFIG                         = 0x1B, // R/W
            REG_ACCEL_CONFIG                        = 0x1C, // R/W
            REG_FF_THR                              = 0x1D, // R/W
            REG_FF_DUR                              = 0x1E, // R/W
            REG_MOT_THR                             = 0x1F, // R/W
            REG_MOT_DUR                             = 0x20, // R/W
            REG_ZRMOT_THR                           = 0x21, // R/W
            REG_ZRMOT_DUR                           = 0x22, // R/W
            REG_FIFO_EN                             = 0x23, // R/W
/*          REG_I2C_MST_CTRL                        = 0x24, // R/W
            REG_I2C_SLV0_ADDR                       = 0x25, // R/W
            REG_I2C_SLV0_REG                        = 0x26, // R/W
            REG_I2C_SLV0_CTRL                       = 0x27, // R/W
            REG_I2C_SLV1_ADDR                       = 0x28, // R/W
            REG_I2C_SLV1_REG                        = 0x29, // R/W
            REG_I2C_SLV1_CTRL                       = 0x2A, // R/W
            REG_I2C_SLV2_ADDR                       = 0x2B, // R/W
            REG_I2C_SLV2_REG                        = 0x2C, // R/W
            REG_I2C_SLV2_CTRL                       = 0x2D, // R/W
            REG_I2C_SLV3_ADDR                       = 0x2E, // R/W
            REG_I2C_SLV3_REG                        = 0x2F, // R/W
            REG_I2C_SLV3_CTRL                       = 0x30, // R/W
            REG_I2C_SLV4_ADDR                       = 0x31, // R/W
            REG_I2C_SLV4_REG                        = 0x32, // R/W
            REG_I2C_SLV4_DO                         = 0x33, // R/W
            REG_I2C_SLV4_CTRL                       = 0x34, // R/W
            REG_I2C_SLV4_DI                         = 0x35, // R  
            REG_I2C_MST_STATUS                      = 0x36, // R            */
            REG_INT_PIN_CFG                         = 0x37, // R/W
            REG_INT_ENABLE                          = 0x38, // R/W
            REG_INT_STATUS                          = 0x3A, // R    
            REG_ACCEL_XOUT_H                        = 0x3B, // R  
            REG_ACCEL_XOUT_L                        = 0x3C, // R  
            REG_ACCEL_YOUT_H                        = 0x3D, // R  
            REG_ACCEL_YOUT_L                        = 0x3E, // R  
            REG_ACCEL_ZOUT_H                        = 0x3F, // R  
            REG_ACCEL_ZOUT_L                        = 0x40, // R  
            REG_TEMP_OUT_H                          = 0x41, // R  
            REG_TEMP_OUT_L                          = 0x42, // R  
            REG_GYRO_XOUT_H                         = 0x43, // R  
            REG_GYRO_XOUT_L                         = 0x44, // R  
            REG_GYRO_YOUT_H                         = 0x45, // R  
            REG_GYRO_YOUT_L                         = 0x46, // R  
            REG_GYRO_ZOUT_H                         = 0x47, // R  
            REG_GYRO_ZOUT_L                         = 0x48, // R  
/*          REG_EXT_SENS_DATA_00                    = 0x49, // R  
            REG_EXT_SENS_DATA_01                    = 0x4A, // R  
            REG_EXT_SENS_DATA_02                    = 0x4B, // R  
            REG_EXT_SENS_DATA_03                    = 0x4C, // R  
            REG_EXT_SENS_DATA_04                    = 0x4D, // R  
            REG_EXT_SENS_DATA_05                    = 0x4E, // R  
            REG_EXT_SENS_DATA_06                    = 0x4F, // R  
            REG_EXT_SENS_DATA_07                    = 0x50, // R  
            REG_EXT_SENS_DATA_08                    = 0x51, // R  
            REG_EXT_SENS_DATA_09                    = 0x52, // R  
            REG_EXT_SENS_DATA_10                    = 0x53, // R  
            REG_EXT_SENS_DATA_11                    = 0x54, // R  
            REG_EXT_SENS_DATA_12                    = 0x55, // R  
            REG_EXT_SENS_DATA_13                    = 0x56, // R  
            REG_EXT_SENS_DATA_14                    = 0x57, // R  
            REG_EXT_SENS_DATA_15                    = 0x58, // R  
            REG_EXT_SENS_DATA_16                    = 0x59, // R  
            REG_EXT_SENS_DATA_17                    = 0x5A, // R  
            REG_EXT_SENS_DATA_18                    = 0x5B, // R  
            REG_EXT_SENS_DATA_19                    = 0x5C, // R  
            REG_EXT_SENS_DATA_20                    = 0x5D, // R  
            REG_EXT_SENS_DATA_21                    = 0x5E, // R  
            REG_EXT_SENS_DATA_22                    = 0x5F, // R  
            REG_EXT_SENS_DATA_23                    = 0x60, // R            */
            REG_MOT_DETECT_STATUS                   = 0x61, // R  
/*          REG_I2C_SLV0_DO                         = 0x63, // R/W
            REG_I2C_SLV1_DO                         = 0x64, // R/W
            REG_I2C_SLV2_DO                         = 0x65, // R/W
            REG_I2C_SLV3_DO                         = 0x66, // R/W          
            REG_I2C_MST_DELAY_CTRL                  = 0x67, // R/W          */
            REG_SIGNAL_PATH_RESET                   = 0x68, // R/W
            REG_MOT_DETECT_CTRL                     = 0x69, // R/W
            REG_USER_CTRL                           = 0x6A, // R/W
            REG_PWR_MGMT_1                          = 0x6B, // R/W
            REG_PWR_MGMT_2                          = 0x6C, // R/W
            REG_FIFO_COUNTH                         = 0x72, // R/W
            REG_FIFO_COUNTL                         = 0x73, // R/W
            REG_FIFO_R_W                            = 0x74, // R/W
            REG_WHO_AM_I                            = 0x75  // R
        };
        
        static const uint8_t AUX_VDDIO_MASK         = BYTE(10000000);        
        enum AuxVDDIOLevel
        {
            AUX_VDDIO_VLOGIC                        = BYTE(00000000),
            AUX_VDDIO_VDD                           = BYTE(10000000)
        };
        
        static const uint8_t EXT_SYNC_MASK          = BYTE(00111000);
        enum ExtFrameSync
        {
            EXT_SYNC_DISABLED                       = BYTE(00000000),
            EXT_SYNC_TEMP_OUT_L                     = BYTE(00001000),
            EXT_SYNC_GYRO_XOUT_L                    = BYTE(00010000),
            EXT_SYNC_GYRO_YOUT_L                    = BYTE(00011000),
            EXT_SYNC_GYRO_ZOUT_L                    = BYTE(00100000),
            EXT_SYNC_ACCEL_XOUT_L                   = BYTE(00101000),
            EXT_SYNC_ACCEL_YOUT_L                   = BYTE(00110000),
            EXT_SYNC_ACCEL_ZOUT_L                   = BYTE(00111000)
        };
        
        static const uint8_t DLPF_MASK              = BYTE(00000111);
        enum DLPFBandwidth
        {
            DLPF_260HZ_256Hz                        = BYTE(00000000),
            DLPF_184HZ_188Hz                        = BYTE(00000001),
            DLPF_94HZ_98HZ                          = BYTE(00000010),
            DLPF_44HZ_42HZ                          = BYTE(00000011),
            DLPF_21HZ_20HZ                          = BYTE(00000100),
            DLPF_10HZ_10HZ                          = BYTE(00000101),
            DLPF_5HZ_5HZ                            = BYTE(00000110),
            DLPF_RESERVED                           = BYTE(00000111)
        };
        
        static const uint8_t GYRO_X_ST_MASK         = BYTE(10000000);
        static const uint8_t GYRO_Y_ST_MASK         = BYTE(01000000);
        static const uint8_t GYRO_Z_ST_MASK         = BYTE(00100000);
        
        static const uint8_t GYRO_RANGE_MASK        = BYTE(00011000);
        enum GyroRange
        {
            GYRO_RANGE_250                          = BYTE(00000000),
            GYRO_RANGE_500                          = BYTE(00001000),
            GYRO_RANGE_1000                         = BYTE(00010000),
            GYRO_RANGE_2000                         = BYTE(00011000)
        };
        
        static const uint8_t ACCEL_X_ST_MASK        = BYTE(10000000);
        static const uint8_t ACCEL_Y_ST_MASK        = BYTE(01000000);
        static const uint8_t ACCEL_Z_ST_MASK        = BYTE(00100000);
        
        static const uint8_t ACCEL_HPF_MASK         = BYTE(00000111);
        enum AccelHPFCutOff
        {
            ACCEL_HPF_RESET                         = BYTE(00000000),
            ACCEL_HPF_5HZ                           = BYTE(00000001),
            ACCEL_HPF_2_5HZ                         = BYTE(00000010),
            ACCEL_HPF_1_25HZ                        = BYTE(00000011),
            ACCEL_HPF_0_63HZ                        = BYTE(00000100),
            ACCEL_HPF_HOLD                          = BYTE(00000111)
        };
        
        static const uint8_t ACCEL_RANGE_MASK       = BYTE(00011000);
        enum AccelRange
        {
            ACCEL_RANGE_2G                          = BYTE(00000000),
            ACCEL_RANGE_4G                          = BYTE(00001000),
            ACCEL_RANGE_8G                          = BYTE(00010000),
            ACCEL_RANGE_16G                         = BYTE(00011000)
        };
        
        static const uint8_t TEMP_FIFO_EN_MASK      = BYTE(10000000);
        static const uint8_t GYRO_X_FIFO_EN_MASK    = BYTE(01000000);
        static const uint8_t GYRO_Y_FIFO_EN_MASK    = BYTE(00100000);
        static const uint8_t GYRO_Z_FIFO_EN_MASK    = BYTE(00010000);
        static const uint8_t ACCEL_FIFO_EN_MASK     = BYTE(00001000);
        
        static const uint8_t INT_LEVEL_MASK         = BYTE(10000000);
        enum InterruptLevel
        {
            INT_LEVEL_ACTIVE_HIGH                   = BYTE(00000000),
            INT_LEVEL_ACTIVE_LOW                    = BYTE(10000000)
        };
        
        static const uint8_t INT_DRIVE_MASK         = BYTE(01000000);
        enum InterruptDrive
        {
            INT_DRIVE_PUSH_PULL                     = BYTE(00000000),
            INT_DRIVE_OPEN_DRAIN                    = BYTE(01000000)
        };
        
        static const uint8_t INT_LATCH_MASK         = BYTE(00100000);
        enum InterruptLatch
        {
            INT_LATCH_50US_PULSE                    = BYTE(00000000),
            INT_LATCH_WAIT_CLEARED                  = BYTE(00100000)
        };
        
        static const uint8_t INT_CLEAR_MASK         = BYTE(00010000);
        enum InterruptClear
        {
            INT_CLEAR_STATUS_ONLY_READ              = BYTE(00000000),
            INT_CLEAR_ANY_READ                      = BYTE(00010000)
        };
        
        static const uint8_t INT_FSYNC_LEVEL_MASK   = BYTE(00001000);
        enum InterruptFSyncLevel
        {
            INT_FSYNC_LEVEL_ACTIVE_HIGH             = BYTE(00000000),
            INT_FSYNC_LEVEL_ACTIVE_LOW              = BYTE(00001000)
        };
        
        static const uint8_t INT_FSYNC_EN_MASK      = BYTE(00000100);
        
        enum Interrupt
        {
            INT_FREEFALL                            = BYTE(10000000),
            INT_MOTION                              = BYTE(01000000),
            INT_ZERO_MOTION                         = BYTE(00100000),
            INT_FIFO_OVERFLOW                       = BYTE(00010000),
/*          INT_I2C_MASTER                          = BYTE(00001000),
            INT_PLL_READY                           = BYTE(00000100),
            INT_DMP_INIT                            = BYTE(00000010),       */
            INT_DATA_READY                          = BYTE(00000001)
        };
        friend inline Interrupt operator|(Interrupt a, Interrupt b) { return static_cast<Interrupt>(static_cast<int>(a) | static_cast<int>(b)); }
        friend inline Interrupt operator&(Interrupt a, Interrupt b) { return static_cast<Interrupt>(static_cast<int>(a) & static_cast<int>(b)); }
        
        enum Motion
        {
            MOT_NEGATIVE_X                          = BYTE(10000000),
            MOT_POSITIVE_X                          = BYTE(01000000),
            MOT_NEGATIVE_Y                          = BYTE(00100000),
            MOT_POSITIVE_Y                          = BYTE(00010000),
            MOT_NEGATIVE_Z                          = BYTE(00001000),
            MOT_POSITIVE_Z                          = BYTE(00000100),
            MOT_ZERO                                = BYTE(00000001)
        };
        friend inline Motion operator|(Motion a, Motion b) { return static_cast<Motion>(static_cast<int>(a) | static_cast<int>(b)); }
        friend inline Motion operator&(Motion a, Motion b) { return static_cast<Motion>(static_cast<int>(a) & static_cast<int>(b)); }
        
        static const uint8_t GYRO_PATH_RESET_MASK   = BYTE(00000100);
        static const uint8_t ACCEL_PATH_RESET_MASK  = BYTE(00000010);
        static const uint8_t TEMP_PATH_RESET_MASK   = BYTE(00000001);
        
        /**
         * basic members
         */
        
        MPU6050(PinName sda, PinName scl, BaseAddress address = ADDRESS_0) : i2c(sda, scl), baseAddress(address)
        { i2c.frequency(500); }
        
        BaseAddress getAddress() { return baseAddress; }         
        
        /**
         * REG_AUX_VDDIO register
         */
         
        bool        getAuxVDDIOLevel(AuxVDDIOLevel *level,  float timeout_secs = defaultTimeout_secs);
        bool        setAuxVDDIOLevel(AuxVDDIOLevel level,   float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_SMPLRT_DIV register
         */
         
        bool        getGyroSampleRateDivider(uint8_t *rateDivider,  float timeout_secs = defaultTimeout_secs);
        bool        setGyroSampleRateDivider(uint8_t rateDivider,   float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_CONFIG register
         */
         
        bool        getExternalFrameSync(ExtFrameSync *frameSync,   float timeout_secs = defaultTimeout_secs);
        bool        setExternalFrameSync(ExtFrameSync frameSync,    float timeout_secs = defaultTimeout_secs);
         
        bool        getDLPFBandwidth(DLPFBandwidth *bandwidth,  float timeout_secs = defaultTimeout_secs);
        bool        setDLPFBandwidth(DLPFBandwidth bandwidth,   float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_GYRO_CONFIG register
         */         
        
        bool        getGyroXSelfTestEnabled(bool *enabled,  float timeout_secs = defaultTimeout_secs);
        bool        setGyroXSelfTestEnabled(bool enabled,   float timeout_secs = defaultTimeout_secs);
        
        bool        getGyroYSelfTestEnabled(bool *enabled,  float timeout_secs = defaultTimeout_secs);
        bool        setGyroYSelfTestEnabled(bool enabled,   float timeout_secs = defaultTimeout_secs);   
        
        bool        getGyroZSelfTestEnabled(bool *enabled,  float timeout_secs = defaultTimeout_secs);
        bool        setGyroZSelfTestEnabled(bool enabled,   float timeout_secs = defaultTimeout_secs); 
        
        bool        getGyroRange(GyroRange *gyroRange,  float timeout_secs = defaultTimeout_secs);
        bool        setGyroRange(GyroRange gyroRange,   float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_ACCEL_CONFIG register
         */
         
        bool        getAccelXSelfTestEnabled(bool *enabled, float timeout_secs = defaultTimeout_secs);
        bool        setAccelXSelfTestEnabled(bool enabled,  float timeout_secs = defaultTimeout_secs);
        
        bool        getAccelYSelfTestEnabled(bool *enabled, float timeout_secs = defaultTimeout_secs);
        bool        setAccelYSelfTestEnabled(bool enabled,  float timeout_secs = defaultTimeout_secs);   
        
        bool        getAccelZSelfTestEnabled(bool *enabled, float timeout_secs = defaultTimeout_secs);
        bool        setAccelZSelfTestEnabled(bool enabled,  float timeout_secs = defaultTimeout_secs); 
        
        bool        getAccelHPFCutOff(AccelHPFCutOff *frequency,    float timeout_secs = defaultTimeout_secs);
        bool        setAccelHPFCutOff(AccelHPFCutOff frequency,     float timeout_secs = defaultTimeout_secs);
        
        bool        getAccelRange(AccelRange *accelRange,   float timeout_secs = defaultTimeout_secs);
        bool        setAccelRange(AccelRange accelRange,    float timeout_secs = defaultTimeout_secs);           
        
        /**
         * REG_FF_THR register
         */
        
        bool        getFreefallDetectionThreshold(uint8_t *threshold,   float timeout_secs = defaultTimeout_secs);
        bool        setFreefallDetectionThreshold(uint8_t threshold,    float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_FF_DUR register
         */
         
        bool        getFreefallDetectionDuration(uint8_t *duration, float timeout_secs = defaultTimeout_secs);
        bool        setFreefallDetectionDuration(uint8_t duration,  float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_MOT_THR register
         */
         
        bool        getMotionDetectionThreshold(uint8_t *threshold, float timeout_secs = defaultTimeout_secs);
        bool        setMotionDetectionThreshold(uint8_t threshold,  float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_MOT_DUR register
         */
         
        bool        getMotionDetectionDuration(uint8_t *duration,   float timeout_secs = defaultTimeout_secs);
        bool        setMotionDetectionDuration(uint8_t duration,    float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_ZRMOT_THR register
         */
         
        bool        getZeroMotionDetectionThreshold(uint8_t *threshold, float timeout_secs = defaultTimeout_secs);
        bool        setZeroMotionDetectionThreshold(uint8_t threshold,  float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_ZRMOT_DUR register
         */
         
        bool        getZeroMotionDetectionDuration(uint8_t *duration,   float timeout_secs = defaultTimeout_secs);
        bool        setZeroMotionDetectionDuration(uint8_t duration,    float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_FIFO_EN register
         */
        
        bool        getTempFIFOEnabled(bool *enabled,   float timeout_secs = defaultTimeout_secs);
        bool        setTempFIFOEnabled(bool enabled,    float timeout_secs = defaultTimeout_secs);
        
        bool        getGyroXFIFOEnabled(bool *enabled,  float timeout_secs = defaultTimeout_secs);
        bool        setGyroXFIFOEnabled(bool enabled,   float timeout_secs = defaultTimeout_secs);   
        
        bool        getGyroYFIFOEnabled(bool *enabled,  float timeout_secs = defaultTimeout_secs);
        bool        setGyroYFIFOEnabled(bool enabled,   float timeout_secs = defaultTimeout_secs); 
        
        bool        getGyroZFIFOEnabled(bool *enabled,  float timeout_secs = defaultTimeout_secs);
        bool        setGyroZFIFOEnabled(bool enabled,   float timeout_secs = defaultTimeout_secs);         
        
        bool        getAccelFIFOEnabled(bool *enabled,  float timeout_secs = defaultTimeout_secs);
        bool        setAccelFIFOEnabled(bool enabled,   float timeout_secs = defaultTimeout_secs); 
        
        /**
         * REG_INT_PIN_CFG register
         */
         
        bool        getInterruptLevel(InterruptLevel *level,    float timeout_secs = defaultTimeout_secs);
        bool        setInterruptLevel(InterruptLevel level,     float timeout_secs = defaultTimeout_secs);
        
        bool        getInterruptDrive(InterruptDrive *drive,    float timeout_secs = defaultTimeout_secs);
        bool        setInterruptDrive(InterruptDrive drive,     float timeout_secs = defaultTimeout_secs); 
        
        bool        getInterruptLatch(InterruptLatch *latch,    float timeout_secs = defaultTimeout_secs);
        bool        setInterruptLatch(InterruptLatch latch,     float timeout_secs = defaultTimeout_secs); 
        
        bool        getInterruptLatchClear(InterruptClear *latchClear,  float timeout_secs = defaultTimeout_secs);
        bool        setInterruptLatchClear(InterruptClear latchClear,   float timeout_secs = defaultTimeout_secs); 
        
        bool        getInterruptFSyncLevel(InterruptFSyncLevel *fsyncLevel, float timeout_secs = defaultTimeout_secs);
        bool        setInterruptFSyncLevel(InterruptFSyncLevel fsyncLevel,  float timeout_secs = defaultTimeout_secs);        
              
        bool        getInterruptFSyncEnabled(bool *enabled, float timeout_secs = defaultTimeout_secs);
        bool        setInterruptFSyncEnabled(bool enabled,  float timeout_secs = defaultTimeout_secs);   
        
        /**
         * REG_INT_ENABLE register
         */
         
        bool        getInterruptsEnabled(Interrupt *interruptSet,   float timeout_secs = defaultTimeout_secs);
        bool        setInterruptsEnabled(Interrupt interruptSet,    float timeout_secs = defaultTimeout_secs);
        
        bool        getInterruptFreefallEnabled(bool *enabled,  float timeout_secs = defaultTimeout_secs);
        bool        setInterruptFreefallEnabled(bool enabled,   float timeout_secs = defaultTimeout_secs); 
        
        bool        getInterruptMotionEnabled(bool *enabled,    float timeout_secs = defaultTimeout_secs);
        bool        setInterruptMotionEnabled(bool enabled,     float timeout_secs = defaultTimeout_secs); 
        
        bool        getInterruptZeroMotionEnabled(bool *enabled,    float timeout_secs = defaultTimeout_secs);
        bool        setInterruptZeroMotionEnabled(bool enabled,     float timeout_secs = defaultTimeout_secs); 
        
        bool        getInterruptFIFOOverflowEnabled(bool *enabled,  float timeout_secs = defaultTimeout_secs);
        bool        setInterruptFIFOOverflowEnabled(bool enabled,   float timeout_secs = defaultTimeout_secs); 
        
        bool        getInterruptDataReadyEnabled(bool *enabled, float timeout_secs = defaultTimeout_secs);
        bool        setInterruptDataReadyEnabled(bool enabled,  float timeout_secs = defaultTimeout_secs); 
        
        /**
         * REG_INT_STATUS register
         */
        
        bool        getInterruptStatuses(Interrupt *interruptSet,   float timeout_secs = defaultTimeout_secs);
        
        bool        getInterruptFreefallStatus(bool *status,    float timeout_secs = defaultTimeout_secs);
        
        bool        getInterruptMotionStatus(bool *status,  float timeout_secs = defaultTimeout_secs); 
        
        bool        getInterruptZeroMotionStatus(bool *status,  float timeout_secs = defaultTimeout_secs);
        
        bool        getInterruptFIFOOverflowStatus(bool *status,    float timeout_secs = defaultTimeout_secs);
        
        bool        getInterruptDataReadyStatus(bool *status,   float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_ACCEL_XOUT_H 
         * REG_ACCEL_XOUT_L 
         * REG_ACCEL_YOUT_H 
         * REG_ACCEL_YOUT_L 
         * REG_ACCEL_ZOUT_H 
         * REG_ACCEL_ZOUT_L 
         * REG_TEMP_OUT_H 
         * REG_TEMP_OUT_L 
         * REG_GYRO_XOUT_H 
         * REG_GYRO_XOUT_L 
         * REG_GYRO_YOUT_H 
         * REG_GYRO_YOUT_L
         * REG_GYRO_ZOUT_H  
         * REG_GYRO_ZOUT_L registers
         */
         
        /** Acceleration */
         
        bool        getAcceleration(int16_t *ax,    int16_t *ay,    int16_t *az,    float timeout_secs = defaultTimeout_secs);
        
        bool        getAccelerationX(int16_t* ax,   float timeout_secs = defaultTimeout_secs);
        
        bool        getAccelerationY(int16_t* ay,   float timeout_secs = defaultTimeout_secs);
        
        bool        getAccelerationZ(int16_t* az,   float timeout_secs = defaultTimeout_secs);
                 
        /** Temperature */
        
        bool        getTemperature(int16_t* temp,   float timeout_secs = defaultTimeout_secs);
        
        /** Rotation speed */
        
        bool        getRotationSpeed(int16_t *ox,   int16_t *oy,    int16_t *oz,    float timeout_secs = defaultTimeout_secs);
        
        bool        getRotationSpeedX(int16_t* ox,   float timeout_secs = defaultTimeout_secs);
        
        bool        getRotationSpeedY(int16_t* oy,   float timeout_secs = defaultTimeout_secs);
        
        bool        getRotationSpeedZ(int16_t* oz,   float timeout_secs = defaultTimeout_secs);
        
        /** All three */
        
        bool        getMotionAndTemperature(int16_t* ax,    int16_t* ay,    int16_t* az,    
                                            int16_t* ox,    int16_t* oy,    int16_t* oz,
                                            int16_t* temp,  float timeout_secs = defaultTimeout_secs);
                                            
        bool        getMotionAndTemperature(MPU6050SensorReading *sensorReading,    float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_MOT_DETECT_STATUS register
         */
         
        bool        getMotionStatus(Motion *motionSet,  float timeout_secs = defaultTimeout_secs);
        
        bool        getNegativeXMotionDetected(bool *detected,  float timeout_secs = defaultTimeout_secs);
        
        bool        getPositiveXMotionDetected(bool *detected,  float timeout_secs = defaultTimeout_secs); 
        
        bool        getNegativeYMotionDetected(bool *detected,  float timeout_secs = defaultTimeout_secs);
        
        bool        getPositiveYMotionDetected(bool *detected,  float timeout_secs = defaultTimeout_secs);
        
        bool        getNegativeZMotionDetected(bool *detected,  float timeout_secs = defaultTimeout_secs);
        
        bool        getPositiveZMotionDetected(bool *detected,  float timeout_secs = defaultTimeout_secs);
        
        bool        getZeroMotionDetected(bool *detected,   float timeout_secs = defaultTimeout_secs);
        
        /**
         * REG_SIGNAL_PATH_RESET register
         */
         
        bool        resetGyroscopeSignalPath(float timeout_secs = defaultTimeout_secs);
        
        bool        resetAccelerometerSignalPath(float timeout_secs = defaultTimeout_secs);
        
        bool        resetTemperatureSignalPath(float timeout_secs = defaultTimeout_secs);
                 
        /**
         * Read and write registers
         */
         
        bool        read(Register reg,  uint8_t *data,  float timeout_secs = defaultTimeout_secs);        
        bool        read(Register reg,  uint8_t *data,  size_t length,  float timeout_secs = defaultTimeout_secs);
        
        bool        write(Register reg, uint8_t data,   float timeout_secs = defaultTimeout_secs);        
        bool        write(Register reg, uint8_t *data,  size_t length,  float timeout_secs = defaultTimeout_secs);
        
    private:
        static const float retryDelay_secs      = 0.005;
        static const float defaultTimeout_secs  = 0.1;      // makes a maximum of 20 tries
    
        I2C         i2c;
        BaseAddress baseAddress;
        
        union
        {
            struct
            {
                uint8_t ax_h,   ax_l;
                uint8_t ay_h,   ay_l;
                uint8_t az_h,   az_l;
                
                uint8_t temp_h, temp_l;
                
                uint8_t ox_h,   ox_l;
                uint8_t oy_h,   oy_l;
                uint8_t oz_h,   oz_l;
            } reg;
            
            MPU6050SensorReading value;
        } converter;
};

#endif